Revision 249069a1 lib/cmdlib.py

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

  

Also available in: Unified diff