Revision 249069a1
b/lib/cmdlib.py | ||
---|---|---|
3203 | 3203 |
return cmd[0], cmd |
3204 | 3204 |
|
3205 | 3205 |
|
3206 |
class LUAddMDDRBDComponent(LogicalUnit): |
|
3207 |
"""Adda new mirror member to an instance's disk. |
|
3208 |
|
|
3209 |
""" |
|
3210 |
HPATH = "mirror-add" |
|
3211 |
HTYPE = constants.HTYPE_INSTANCE |
|
3212 |
_OP_REQP = ["instance_name", "remote_node", "disk_name"] |
|
3213 |
|
|
3214 |
def BuildHooksEnv(self): |
|
3215 |
"""Build hooks env. |
|
3216 |
|
|
3217 |
This runs on the master, the primary and all the secondaries. |
|
3218 |
|
|
3219 |
""" |
|
3220 |
env = { |
|
3221 |
"NEW_SECONDARY": self.op.remote_node, |
|
3222 |
"DISK_NAME": self.op.disk_name, |
|
3223 |
} |
|
3224 |
env.update(_BuildInstanceHookEnvByObject(self.instance)) |
|
3225 |
nl = [self.sstore.GetMasterNode(), self.instance.primary_node, |
|
3226 |
self.op.remote_node,] + list(self.instance.secondary_nodes) |
|
3227 |
return env, nl, nl |
|
3228 |
|
|
3229 |
def CheckPrereq(self): |
|
3230 |
"""Check prerequisites. |
|
3231 |
|
|
3232 |
This checks that the instance is in the cluster. |
|
3233 |
|
|
3234 |
""" |
|
3235 |
instance = self.cfg.GetInstanceInfo( |
|
3236 |
self.cfg.ExpandInstanceName(self.op.instance_name)) |
|
3237 |
if instance is None: |
|
3238 |
raise errors.OpPrereqError("Instance '%s' not known" % |
|
3239 |
self.op.instance_name) |
|
3240 |
self.instance = instance |
|
3241 |
|
|
3242 |
remote_node = self.cfg.ExpandNodeName(self.op.remote_node) |
|
3243 |
if remote_node is None: |
|
3244 |
raise errors.OpPrereqError("Node '%s' not known" % self.op.remote_node) |
|
3245 |
self.remote_node = remote_node |
|
3246 |
|
|
3247 |
if remote_node == instance.primary_node: |
|
3248 |
raise errors.OpPrereqError("The specified node is the primary node of" |
|
3249 |
" the instance.") |
|
3250 |
|
|
3251 |
if instance.disk_template != constants.DT_REMOTE_RAID1: |
|
3252 |
raise errors.OpPrereqError("Instance's disk layout is not" |
|
3253 |
" remote_raid1.") |
|
3254 |
for disk in instance.disks: |
|
3255 |
if disk.iv_name == self.op.disk_name: |
|
3256 |
break |
|
3257 |
else: |
|
3258 |
raise errors.OpPrereqError("Can't find this device ('%s') in the" |
|
3259 |
" instance." % self.op.disk_name) |
|
3260 |
if len(disk.children) > 1: |
|
3261 |
raise errors.OpPrereqError("The device already has two slave devices." |
|
3262 |
" This would create a 3-disk raid1 which we" |
|
3263 |
" don't allow.") |
|
3264 |
self.disk = disk |
|
3265 |
|
|
3266 |
def Exec(self, feedback_fn): |
|
3267 |
"""Add the mirror component |
|
3268 |
|
|
3269 |
""" |
|
3270 |
disk = self.disk |
|
3271 |
instance = self.instance |
|
3272 |
|
|
3273 |
remote_node = self.remote_node |
|
3274 |
lv_names = [".%s_%s" % (disk.iv_name, suf) for suf in ["data", "meta"]] |
|
3275 |
names = _GenerateUniqueNames(self.cfg, lv_names) |
|
3276 |
new_drbd = _GenerateMDDRBDBranch(self.cfg, instance.primary_node, |
|
3277 |
remote_node, disk.size, names) |
|
3278 |
|
|
3279 |
logger.Info("adding new mirror component on secondary") |
|
3280 |
#HARDCODE |
|
3281 |
if not _CreateBlockDevOnSecondary(self.cfg, remote_node, instance, |
|
3282 |
new_drbd, False, |
|
3283 |
_GetInstanceInfoText(instance)): |
|
3284 |
raise errors.OpExecError("Failed to create new component on secondary" |
|
3285 |
" node %s" % remote_node) |
|
3286 |
|
|
3287 |
logger.Info("adding new mirror component on primary") |
|
3288 |
#HARDCODE |
|
3289 |
if not _CreateBlockDevOnPrimary(self.cfg, instance.primary_node, |
|
3290 |
instance, new_drbd, |
|
3291 |
_GetInstanceInfoText(instance)): |
|
3292 |
# remove secondary dev |
|
3293 |
self.cfg.SetDiskID(new_drbd, remote_node) |
|
3294 |
rpc.call_blockdev_remove(remote_node, new_drbd) |
|
3295 |
raise errors.OpExecError("Failed to create volume on primary") |
|
3296 |
|
|
3297 |
# the device exists now |
|
3298 |
# call the primary node to add the mirror to md |
|
3299 |
logger.Info("adding new mirror component to md") |
|
3300 |
if not rpc.call_blockdev_addchildren(instance.primary_node, |
|
3301 |
disk, [new_drbd]): |
|
3302 |
logger.Error("Can't add mirror compoment to md!") |
|
3303 |
self.cfg.SetDiskID(new_drbd, remote_node) |
|
3304 |
if not rpc.call_blockdev_remove(remote_node, new_drbd): |
|
3305 |
logger.Error("Can't rollback on secondary") |
|
3306 |
self.cfg.SetDiskID(new_drbd, instance.primary_node) |
|
3307 |
if not rpc.call_blockdev_remove(instance.primary_node, new_drbd): |
|
3308 |
logger.Error("Can't rollback on primary") |
|
3309 |
raise errors.OpExecError("Can't add mirror component to md array") |
|
3310 |
|
|
3311 |
disk.children.append(new_drbd) |
|
3312 |
|
|
3313 |
self.cfg.AddInstance(instance) |
|
3314 |
|
|
3315 |
_WaitForSync(self.cfg, instance, self.proc) |
|
3316 |
|
|
3317 |
return 0 |
|
3318 |
|
|
3319 |
|
|
3320 |
class LURemoveMDDRBDComponent(LogicalUnit): |
|
3321 |
"""Remove a component from a remote_raid1 disk. |
|
3322 |
|
|
3323 |
""" |
|
3324 |
HPATH = "mirror-remove" |
|
3325 |
HTYPE = constants.HTYPE_INSTANCE |
|
3326 |
_OP_REQP = ["instance_name", "disk_name", "disk_id"] |
|
3327 |
|
|
3328 |
def BuildHooksEnv(self): |
|
3329 |
"""Build hooks env. |
|
3330 |
|
|
3331 |
This runs on the master, the primary and all the secondaries. |
|
3332 |
|
|
3333 |
""" |
|
3334 |
env = { |
|
3335 |
"DISK_NAME": self.op.disk_name, |
|
3336 |
"DISK_ID": self.op.disk_id, |
|
3337 |
"OLD_SECONDARY": self.old_secondary, |
|
3338 |
} |
|
3339 |
env.update(_BuildInstanceHookEnvByObject(self.instance)) |
|
3340 |
nl = [self.sstore.GetMasterNode(), |
|
3341 |
self.instance.primary_node] + list(self.instance.secondary_nodes) |
|
3342 |
return env, nl, nl |
|
3343 |
|
|
3344 |
def CheckPrereq(self): |
|
3345 |
"""Check prerequisites. |
|
3346 |
|
|
3347 |
This checks that the instance is in the cluster. |
|
3348 |
|
|
3349 |
""" |
|
3350 |
instance = self.cfg.GetInstanceInfo( |
|
3351 |
self.cfg.ExpandInstanceName(self.op.instance_name)) |
|
3352 |
if instance is None: |
|
3353 |
raise errors.OpPrereqError("Instance '%s' not known" % |
|
3354 |
self.op.instance_name) |
|
3355 |
self.instance = instance |
|
3356 |
|
|
3357 |
if instance.disk_template != constants.DT_REMOTE_RAID1: |
|
3358 |
raise errors.OpPrereqError("Instance's disk layout is not" |
|
3359 |
" remote_raid1.") |
|
3360 |
for disk in instance.disks: |
|
3361 |
if disk.iv_name == self.op.disk_name: |
|
3362 |
break |
|
3363 |
else: |
|
3364 |
raise errors.OpPrereqError("Can't find this device ('%s') in the" |
|
3365 |
" instance." % self.op.disk_name) |
|
3366 |
for child in disk.children: |
|
3367 |
if (child.dev_type == constants.LD_DRBD7 and |
|
3368 |
child.logical_id[2] == self.op.disk_id): |
|
3369 |
break |
|
3370 |
else: |
|
3371 |
raise errors.OpPrereqError("Can't find the device with this port.") |
|
3372 |
|
|
3373 |
if len(disk.children) < 2: |
|
3374 |
raise errors.OpPrereqError("Cannot remove the last component from" |
|
3375 |
" a mirror.") |
|
3376 |
self.disk = disk |
|
3377 |
self.child = child |
|
3378 |
if self.child.logical_id[0] == instance.primary_node: |
|
3379 |
oid = 1 |
|
3380 |
else: |
|
3381 |
oid = 0 |
|
3382 |
self.old_secondary = self.child.logical_id[oid] |
|
3383 |
|
|
3384 |
def Exec(self, feedback_fn): |
|
3385 |
"""Remove the mirror component |
|
3386 |
|
|
3387 |
""" |
|
3388 |
instance = self.instance |
|
3389 |
disk = self.disk |
|
3390 |
child = self.child |
|
3391 |
logger.Info("remove mirror component") |
|
3392 |
self.cfg.SetDiskID(disk, instance.primary_node) |
|
3393 |
if not rpc.call_blockdev_removechildren(instance.primary_node, |
|
3394 |
disk, [child]): |
|
3395 |
raise errors.OpExecError("Can't remove child from mirror.") |
|
3396 |
|
|
3397 |
for node in child.logical_id[:2]: |
|
3398 |
self.cfg.SetDiskID(child, node) |
|
3399 |
if not rpc.call_blockdev_remove(node, child): |
|
3400 |
logger.Error("Warning: failed to remove device from node %s," |
|
3401 |
" continuing operation." % node) |
|
3402 |
|
|
3403 |
disk.children.remove(child) |
|
3404 |
self.cfg.AddInstance(instance) |
|
3405 |
|
|
3406 |
|
|
3407 | 3206 |
class LUReplaceDisks(LogicalUnit): |
3408 | 3207 |
"""Replace the disks of an instance. |
3409 | 3208 |
|
b/lib/mcpu.py | ||
---|---|---|
68 | 68 |
opcodes.OpStartupInstance: cmdlib.LUStartupInstance, |
69 | 69 |
opcodes.OpRebootInstance: cmdlib.LURebootInstance, |
70 | 70 |
opcodes.OpDeactivateInstanceDisks: cmdlib.LUDeactivateInstanceDisks, |
71 |
opcodes.OpAddMDDRBDComponent: cmdlib.LUAddMDDRBDComponent, |
|
72 |
opcodes.OpRemoveMDDRBDComponent: cmdlib.LURemoveMDDRBDComponent, |
|
73 | 71 |
opcodes.OpReplaceDisks: cmdlib.LUReplaceDisks, |
74 | 72 |
opcodes.OpFailoverInstance: cmdlib.LUFailoverInstance, |
75 | 73 |
opcodes.OpConnectConsole: cmdlib.LUConnectConsole, |
b/lib/opcodes.py | ||
---|---|---|
301 | 301 |
"ignore_secondaries" ] |
302 | 302 |
|
303 | 303 |
|
304 |
class OpAddMDDRBDComponent(OpCode): |
|
305 |
"""Add a MD-DRBD component.""" |
|
306 |
OP_ID = "OP_INSTANCE_ADD_MDDRBD" |
|
307 |
__slots__ = ["instance_name", "remote_node", "disk_name"] |
|
308 |
|
|
309 |
|
|
310 |
class OpRemoveMDDRBDComponent(OpCode): |
|
311 |
"""Remove a MD-DRBD component.""" |
|
312 |
OP_ID = "OP_INSTANCE_REMOVE_MDDRBD" |
|
313 |
__slots__ = ["instance_name", "disk_name", "disk_id"] |
|
314 |
|
|
315 |
|
|
316 | 304 |
class OpReplaceDisks(OpCode): |
317 | 305 |
"""Replace the disks of an instance.""" |
318 | 306 |
OP_ID = "OP_INSTANCE_REPLACE_DISKS" |
b/man/gnt-instance.sgml | ||
---|---|---|
896 | 896 |
</refsect3> |
897 | 897 |
|
898 | 898 |
<refsect3> |
899 |
<title>ADD-MIRROR</title> |
|
900 |
<cmdsynopsis> |
|
901 |
<command>add-mirror</command> |
|
902 |
<arg choice="req">-b <replaceable>sdX</replaceable></arg> |
|
903 |
<arg choice="req">-n <replaceable>node</replaceable></arg> |
|
904 |
<arg choice="req"><replaceable>instance</replaceable></arg> |
|
905 |
</cmdsynopsis> |
|
906 |
<para> |
|
907 |
Adds a new mirror to the disk layout of the instance, if the |
|
908 |
instance has a remote raid disk layout. |
|
909 |
|
|
910 |
The new mirror member will be between the instance's primary |
|
911 |
node and the node given with the <option>-n</option> option. |
|
912 |
</para> |
|
913 |
</refsect3> |
|
914 |
|
|
915 |
<refsect3> |
|
916 |
<title>REMOVE-MIRROR</title> |
|
917 |
|
|
918 |
<cmdsynopsis> |
|
919 |
<command>removemirror</command> |
|
920 |
<arg choice="req">-b <replaceable>sdX</replaceable></arg> |
|
921 |
<arg choice="req">-p <replaceable>id</replaceable></arg> |
|
922 |
<arg choice="req"><replaceable>instance</replaceable></arg> |
|
923 |
</cmdsynopsis> |
|
924 |
<para> |
|
925 |
Removes a mirror componenent from the disk layout of the |
|
926 |
instance, if the instance has a remote raid disk layout. |
|
927 |
</para> |
|
928 |
|
|
929 |
<para> |
|
930 |
You need to specifiy on which disk to act on using the |
|
931 |
<option>-b</option> option (either <filename>sda</filename> |
|
932 |
or <filename>sdb</filename>) and the mirror component, which |
|
933 |
is identified by the <option>-p</option> option. You can |
|
934 |
find the list of valid identifiers with the |
|
935 |
<command>info</command> command. |
|
936 |
</para> |
|
937 |
|
|
938 |
<refsect3> |
|
939 | 899 |
<title>ACTIVATE-DISKS</title> |
940 | 900 |
|
941 | 901 |
<cmdsynopsis> |
b/scripts/gnt-instance | ||
---|---|---|
435 | 435 |
return 0 |
436 | 436 |
|
437 | 437 |
|
438 |
def AddMDDRBDComponent(opts, args): |
|
439 |
"""Add a new component to a remote_raid1 disk. |
|
440 |
|
|
441 |
Args: |
|
442 |
opts - class with options as members |
|
443 |
args - list with a single element, the instance name |
|
444 |
|
|
445 |
""" |
|
446 |
op = opcodes.OpAddMDDRBDComponent(instance_name=args[0], |
|
447 |
disk_name=opts.disk, |
|
448 |
remote_node=opts.node) |
|
449 |
SubmitOpCode(op) |
|
450 |
return 0 |
|
451 |
|
|
452 |
|
|
453 |
def RemoveMDDRBDComponent(opts, args): |
|
454 |
"""Remove a component from a remote_raid1 disk. |
|
455 |
|
|
456 |
Args: |
|
457 |
opts - class with options as members |
|
458 |
args - list with a single element, the instance name |
|
459 |
|
|
460 |
""" |
|
461 |
op = opcodes.OpRemoveMDDRBDComponent(instance_name=args[0], |
|
462 |
disk_name=opts.disk, |
|
463 |
disk_id=opts.port) |
|
464 |
SubmitOpCode(op) |
|
465 |
return 0 |
|
466 |
|
|
467 |
|
|
468 | 438 |
def ReplaceDisks(opts, args): |
469 | 439 |
"""Replace the disks of an instance |
470 | 440 |
|
... | ... | |
792 | 762 |
'add': (AddInstance, ARGS_ONE, add_opts, |
793 | 763 |
"[opts...] <name>", |
794 | 764 |
"Creates and adds a new instance to the cluster"), |
795 |
'add-mirror': (AddMDDRBDComponent, ARGS_ONE, |
|
796 |
[DEBUG_OPT, node_opt, |
|
797 |
make_option("-b", "--disk", dest="disk", metavar="sdX", |
|
798 |
help=("The name of the instance disk for which to" |
|
799 |
" add the mirror"))], |
|
800 |
"-n node -b disk <instance>", |
|
801 |
"Creates a new mirror for the instance"), |
|
802 | 765 |
'console': (ConnectToInstanceConsole, ARGS_ONE, [DEBUG_OPT], |
803 | 766 |
"<instance>", |
804 | 767 |
"Opens a console on the specified instance"), |
... | ... | |
833 | 796 |
" process (shutdown, disk removal, etc.)")), |
834 | 797 |
], |
835 | 798 |
"[-f] <instance>", "Shuts down the instance and removes it"), |
836 |
'remove-mirror': (RemoveMDDRBDComponent, ARGS_ONE, |
|
837 |
[DEBUG_OPT, node_opt, |
|
838 |
make_option("-b", "--disk", dest="disk", metavar="sdX", |
|
839 |
help=("The name of the instance disk" |
|
840 |
" for which to add the mirror")), |
|
841 |
make_option("-p", "--port", dest="port", metavar="PORT", |
|
842 |
help=("The port of the drbd device" |
|
843 |
" which to remove from the mirror"), |
|
844 |
type="int"), |
|
845 |
], |
|
846 |
"-b disk -p port <instance>", |
|
847 |
"Removes a mirror from the instance"), |
|
848 | 799 |
'rename': (RenameInstance, ARGS_FIXED(2), |
849 | 800 |
[DEBUG_OPT, |
850 | 801 |
make_option("--no-ip-check", dest="ignore_ip", |
Also available in: Unified diff