1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 """DRBD command generating classes"""
32
33 import logging
34 import shlex
35
36 from ganeti import constants
37 from ganeti import errors
41 """Base class for DRBD command generators.
42
43 This class defines the interface for the command generators and holds shared
44 code.
45
46 """
49
51 raise NotImplementedError
52
55
57 raise NotImplementedError
58
59 - def GenNetInitCmd(self, minor, family, lhost, lport, rhost, rport, protocol,
60 dual_pri, hmac, secret, params):
61 raise NotImplementedError
62
64 raise NotImplementedError
65
67 raise NotImplementedError
68
70 raise NotImplementedError
71
73 raise NotImplementedError
74
76 raise NotImplementedError
77
79 raise NotImplementedError
80
82 raise NotImplementedError
83
85 raise NotImplementedError
86
88 raise NotImplementedError
89
90 @staticmethod
92 """Return the path to a drbd device for a given minor.
93
94 """
95 return "/dev/drbd%d" % minor
96
99 """Generates drbdsetup commands suited for the DRBD <= 8.3 syntax.
100
101 """
102
103 _DISABLE_DISK_OPTION = "--no-disk-barrier"
104 _DISABLE_DRAIN_OPTION = "--no-disk-drain"
105 _DISABLE_FLUSH_OPTION = "--no-disk-flushes"
106 _DISABLE_META_FLUSH_OPTION = "--no-md-flushes"
107
110
112 return ["drbdsetup", self._DevPath(minor), "show"]
113
117
119 args = ["drbdsetup", self._DevPath(minor), "disk",
120 data_dev, meta_dev, "0",
121 "-e", "detach",
122 "--create-device"]
123 if size_mb:
124 args.extend(["-d", "%sm" % size_mb])
125
126 vmaj = self._version["k_major"]
127 vmin = self._version["k_minor"]
128 vrel = self._version["k_point"]
129
130 barrier_args = \
131 self._ComputeDiskBarrierArgs(vmaj, vmin, vrel,
132 params[constants.LDP_BARRIERS],
133 params[constants.LDP_NO_META_FLUSH])
134 args.extend(barrier_args)
135
136 if params[constants.LDP_DISK_CUSTOM]:
137 args.extend(shlex.split(params[constants.LDP_DISK_CUSTOM]))
138
139 return [args]
140
141 - def GenNetInitCmd(self, minor, family, lhost, lport, rhost, rport, protocol,
142 dual_pri, hmac, secret, params):
143 args = ["drbdsetup", self._DevPath(minor), "net",
144 "%s:%s:%s" % (family, lhost, lport),
145 "%s:%s:%s" % (family, rhost, rport), protocol,
146 "-A", "discard-zero-changes",
147 "-B", "consensus",
148 "--create-device",
149 ]
150 if dual_pri:
151 args.append("-m")
152 if hmac and secret:
153 args.extend(["-a", hmac, "-x", secret])
154
155 if params[constants.LDP_NET_CUSTOM]:
156 args.extend(shlex.split(params[constants.LDP_NET_CUSTOM]))
157
158 return args
159
161 args = ["drbdsetup", self._DevPath(minor), "syncer"]
162 if params[constants.LDP_DYNAMIC_RESYNC]:
163 vmin = self._version["k_minor"]
164 vrel = self._version["k_point"]
165
166
167
168 if vmin != 3 or vrel < 9:
169 msg = ("The current DRBD version (8.%d.%d) does not support the "
170 "dynamic resync speed controller" % (vmin, vrel))
171 logging.error(msg)
172 return [msg]
173
174 if params[constants.LDP_PLAN_AHEAD] == 0:
175 msg = ("A value of 0 for c-plan-ahead disables the dynamic sync speed"
176 " controller at DRBD level. If you want to disable it, please"
177 " set the dynamic-resync disk parameter to False.")
178 logging.error(msg)
179 return [msg]
180
181
182 args.extend(["--c-plan-ahead", params[constants.LDP_PLAN_AHEAD],
183 "--c-fill-target", params[constants.LDP_FILL_TARGET],
184 "--c-delay-target", params[constants.LDP_DELAY_TARGET],
185 "--c-max-rate", params[constants.LDP_MAX_RATE],
186 "--c-min-rate", params[constants.LDP_MIN_RATE],
187 ])
188
189 else:
190 args.extend(["-r", "%d" % params[constants.LDP_RESYNC_RATE]])
191
192 args.append("--create-device")
193
194 return args
195
197 return ["drbdsetup", self._DevPath(minor), "pause-sync"]
198
200 return ["drbdsetup", self._DevPath(minor), "resume-sync"]
201
203 cmd = ["drbdsetup", self._DevPath(minor), "primary"]
204
205 if force:
206 cmd.append("-o")
207
208 return cmd
209
211 return ["drbdsetup", self._DevPath(minor), "secondary"]
212
214 return ["drbdsetup", self._DevPath(minor), "detach"]
215
217 return ["drbdsetup", self._DevPath(minor), "disconnect"]
218
220 return ["drbdsetup", self._DevPath(minor), "down"]
221
223 return ["drbdsetup", self._DevPath(minor), "resize", "-s", "%dm" % size_mb]
224
225 @classmethod
228 """Compute the DRBD command line parameters for disk barriers
229
230 Returns a list of the disk barrier parameters as requested via the
231 disabled_barriers and disable_meta_flush arguments, and according to the
232 supported ones in the DRBD version vmaj.vmin.vrel
233
234 If the desired option is unsupported, raises errors.BlockDeviceError.
235
236 """
237 disabled_barriers_set = frozenset(disabled_barriers)
238 if not disabled_barriers_set in constants.DRBD_VALID_BARRIER_OPT:
239 raise errors.BlockDeviceError("%s is not a valid option set for DRBD"
240 " barriers" % disabled_barriers)
241
242 args = []
243
244
245
246 if not vmaj == 8 and vmin in (0, 2, 3):
247 raise errors.BlockDeviceError("Unsupported DRBD version: %d.%d.%d" %
248 (vmaj, vmin, vrel))
249
250 def _AppendOrRaise(option, min_version):
251 """Helper for DRBD options"""
252 if min_version is not None and vrel >= min_version:
253 args.append(option)
254 else:
255 raise errors.BlockDeviceError("Could not use the option %s as the"
256 " DRBD version %d.%d.%d does not support"
257 " it." % (option, vmaj, vmin, vrel))
258
259
260
261
262 meta_flush_supported = disk_flush_supported = {
263 0: 12,
264 2: 7,
265 3: 0,
266 }
267
268 disk_drain_supported = {
269 2: 7,
270 3: 0,
271 }
272
273 disk_barriers_supported = {
274 3: 0,
275 }
276
277
278 if disable_meta_flush:
279 _AppendOrRaise(cls._DISABLE_META_FLUSH_OPTION,
280 meta_flush_supported.get(vmin, None))
281
282
283 if constants.DRBD_B_DISK_FLUSH in disabled_barriers_set:
284 _AppendOrRaise(cls._DISABLE_FLUSH_OPTION,
285 disk_flush_supported.get(vmin, None))
286
287
288 if constants.DRBD_B_DISK_DRAIN in disabled_barriers_set:
289 _AppendOrRaise(cls._DISABLE_DRAIN_OPTION,
290 disk_drain_supported.get(vmin, None))
291
292
293 if constants.DRBD_B_DISK_BARRIERS in disabled_barriers_set:
294 _AppendOrRaise(cls._DISABLE_DISK_OPTION,
295 disk_barriers_supported.get(vmin, None))
296
297 return args
298
301 """Generates drbdsetup commands suited for the DRBD >= 8.4 syntax.
302
303 """
304
305 _DISABLE_DISK_OPTION = "--disk-barrier=no"
306 _DISABLE_DRAIN_OPTION = "--disk-drain=no"
307 _DISABLE_FLUSH_OPTION = "--disk-flushes=no"
308 _DISABLE_META_FLUSH_OPTION = "--md-flushes=no"
309
312
314 return ["drbdsetup", "show", minor]
315
319
321 cmds = []
322
323 cmds.append(["drbdsetup", "new-resource", self._GetResource(minor)])
324 cmds.append(["drbdsetup", "new-minor", self._GetResource(minor),
325 str(minor), "0"])
326
327
328 cmds.append(["drbdmeta", self._DevPath(minor),
329 "v08", meta_dev, "flex-external", "apply-al"])
330
331 attach_cmd = ["drbdsetup", "attach", minor, data_dev, meta_dev, "flexible",
332 "--on-io-error=detach"]
333 if size_mb:
334 attach_cmd.extend(["--size", "%sm" % size_mb])
335
336 barrier_args = \
337 self._ComputeDiskBarrierArgs(params[constants.LDP_BARRIERS],
338 params[constants.LDP_NO_META_FLUSH])
339 attach_cmd.extend(barrier_args)
340
341 if params[constants.LDP_DISK_CUSTOM]:
342 attach_cmd.extend(shlex.split(params[constants.LDP_DISK_CUSTOM]))
343
344 cmds.append(attach_cmd)
345
346 return cmds
347
348 - def GenNetInitCmd(self, minor, family, lhost, lport, rhost, rport, protocol,
349 dual_pri, hmac, secret, params):
350 args = ["drbdsetup", "connect", self._GetResource(minor),
351 "%s:%s:%s" % (family, lhost, lport),
352 "%s:%s:%s" % (family, rhost, rport),
353 "--protocol", protocol,
354 "--after-sb-0pri", "discard-zero-changes",
355 "--after-sb-1pri", "consensus"
356 ]
357 if dual_pri:
358 args.append("--allow-two-primaries")
359 if hmac and secret:
360 args.extend(["--cram-hmac-alg", hmac, "--shared-secret", secret])
361
362 if params[constants.LDP_NET_CUSTOM]:
363 args.extend(shlex.split(params[constants.LDP_NET_CUSTOM]))
364
365 return args
366
368 args = ["drbdsetup", "disk-options", minor]
369 if params[constants.LDP_DYNAMIC_RESYNC]:
370 if params[constants.LDP_PLAN_AHEAD] == 0:
371 msg = ("A value of 0 for c-plan-ahead disables the dynamic sync speed"
372 " controller at DRBD level. If you want to disable it, please"
373 " set the dynamic-resync disk parameter to False.")
374 logging.error(msg)
375 return [msg]
376
377
378 args.extend(["--c-plan-ahead", params[constants.LDP_PLAN_AHEAD],
379 "--c-fill-target", params[constants.LDP_FILL_TARGET],
380 "--c-delay-target", params[constants.LDP_DELAY_TARGET],
381 "--c-max-rate", params[constants.LDP_MAX_RATE],
382 "--c-min-rate", params[constants.LDP_MIN_RATE],
383 ])
384
385 else:
386 args.extend(["--resync-rate", "%d" % params[constants.LDP_RESYNC_RATE]])
387
388 return args
389
391 return ["drbdsetup", "pause-sync", minor]
392
394 return ["drbdsetup", "resume-sync", minor]
395
397 cmd = ["drbdsetup", "primary", minor]
398
399 if force:
400 cmd.append("--force")
401
402 return cmd
403
405 return ["drbdsetup", "secondary", minor]
406
408 return ["drbdsetup", "detach", minor]
409
411 return ["drbdsetup", "disconnect",
412 "%s:%s:%s" % (family, lhost, lport),
413 "%s:%s:%s" % (family, rhost, rport)]
414
417
419 return ["drbdsetup", "resize", minor, "--size", "%dm" % size_mb]
420
421 @staticmethod
423 """Return the resource name for a given minor.
424
425 Currently we don't support DRBD volumes which share a resource, so we
426 generate the resource name based on the minor the resulting volumes is
427 assigned to.
428
429 """
430 return "resource%d" % minor
431
432 @classmethod
461