- # build ssh cmdline
- argv = ["ssh", "-q", "-t"]
- argv.extend(ssh.KNOWN_HOSTS_OPTS)
- argv.extend(ssh.BATCH_MODE_OPTS)
- argv.append(node)
- argv.append(console_cmd)
- return "ssh", argv
-
-
-class LUAddMDDRBDComponent(LogicalUnit):
- """Adda new mirror member to an instance's disk.
-
- """
- HPATH = "mirror-add"
- HTYPE = constants.HTYPE_INSTANCE
- _OP_REQP = ["instance_name", "remote_node", "disk_name"]
-
- def BuildHooksEnv(self):
- """Build hooks env.
-
- This runs on the master, the primary and all the secondaries.
-
- """
- env = {
- "NEW_SECONDARY": self.op.remote_node,
- "DISK_NAME": self.op.disk_name,
- }
- env.update(_BuildInstanceHookEnvByObject(self.instance))
- nl = [self.sstore.GetMasterNode(), self.instance.primary_node,
- self.op.remote_node,] + list(self.instance.secondary_nodes)
- return env, nl, nl
-
- def CheckPrereq(self):
- """Check prerequisites.
-
- This checks that the instance is in the cluster.
-
- """
- instance = self.cfg.GetInstanceInfo(
- self.cfg.ExpandInstanceName(self.op.instance_name))
- if instance is None:
- raise errors.OpPrereqError("Instance '%s' not known" %
- self.op.instance_name)
- self.instance = instance
-
- remote_node = self.cfg.ExpandNodeName(self.op.remote_node)
- if remote_node is None:
- raise errors.OpPrereqError("Node '%s' not known" % self.op.remote_node)
- self.remote_node = remote_node
-
- if remote_node == instance.primary_node:
- raise errors.OpPrereqError("The specified node is the primary node of"
- " the instance.")
-
- if instance.disk_template != constants.DT_REMOTE_RAID1:
- raise errors.OpPrereqError("Instance's disk layout is not"
- " remote_raid1.")
- for disk in instance.disks:
- if disk.iv_name == self.op.disk_name:
- break
- else:
- raise errors.OpPrereqError("Can't find this device ('%s') in the"
- " instance." % self.op.disk_name)
- if len(disk.children) > 1:
- raise errors.OpPrereqError("The device already has two slave devices."
- " This would create a 3-disk raid1 which we"
- " don't allow.")
- self.disk = disk
-
- def Exec(self, feedback_fn):
- """Add the mirror component
-
- """
- disk = self.disk
- instance = self.instance
-
- remote_node = self.remote_node
- lv_names = [".%s_%s" % (disk.iv_name, suf) for suf in ["data", "meta"]]
- names = _GenerateUniqueNames(self.cfg, lv_names)
- new_drbd = _GenerateMDDRBDBranch(self.cfg, instance.primary_node,
- remote_node, disk.size, names)
-
- logger.Info("adding new mirror component on secondary")
- #HARDCODE
- if not _CreateBlockDevOnSecondary(self.cfg, remote_node, instance,
- new_drbd, False,
- _GetInstanceInfoText(instance)):
- raise errors.OpExecError("Failed to create new component on secondary"
- " node %s" % remote_node)
-
- logger.Info("adding new mirror component on primary")
- #HARDCODE
- if not _CreateBlockDevOnPrimary(self.cfg, instance.primary_node,
- instance, new_drbd,
- _GetInstanceInfoText(instance)):
- # remove secondary dev
- self.cfg.SetDiskID(new_drbd, remote_node)
- rpc.call_blockdev_remove(remote_node, new_drbd)
- raise errors.OpExecError("Failed to create volume on primary")
-
- # the device exists now
- # call the primary node to add the mirror to md
- logger.Info("adding new mirror component to md")
- if not rpc.call_blockdev_addchildren(instance.primary_node,
- disk, [new_drbd]):
- logger.Error("Can't add mirror compoment to md!")
- self.cfg.SetDiskID(new_drbd, remote_node)
- if not rpc.call_blockdev_remove(remote_node, new_drbd):
- logger.Error("Can't rollback on secondary")
- self.cfg.SetDiskID(new_drbd, instance.primary_node)
- if not rpc.call_blockdev_remove(instance.primary_node, new_drbd):
- logger.Error("Can't rollback on primary")
- raise errors.OpExecError("Can't add mirror component to md array")
-
- disk.children.append(new_drbd)
-
- self.cfg.AddInstance(instance)
-
- _WaitForSync(self.cfg, instance, self.proc)
-
- return 0
-
-
-class LURemoveMDDRBDComponent(LogicalUnit):
- """Remove a component from a remote_raid1 disk.
-
- """
- HPATH = "mirror-remove"
- HTYPE = constants.HTYPE_INSTANCE
- _OP_REQP = ["instance_name", "disk_name", "disk_id"]
-
- def BuildHooksEnv(self):
- """Build hooks env.
-
- This runs on the master, the primary and all the secondaries.
-
- """
- env = {
- "DISK_NAME": self.op.disk_name,
- "DISK_ID": self.op.disk_id,
- "OLD_SECONDARY": self.old_secondary,
- }
- env.update(_BuildInstanceHookEnvByObject(self.instance))
- nl = [self.sstore.GetMasterNode(),
- self.instance.primary_node] + list(self.instance.secondary_nodes)
- return env, nl, nl
-
- def CheckPrereq(self):
- """Check prerequisites.
-
- This checks that the instance is in the cluster.
-
- """
- instance = self.cfg.GetInstanceInfo(
- self.cfg.ExpandInstanceName(self.op.instance_name))
- if instance is None:
- raise errors.OpPrereqError("Instance '%s' not known" %
- self.op.instance_name)
- self.instance = instance
-
- if instance.disk_template != constants.DT_REMOTE_RAID1:
- raise errors.OpPrereqError("Instance's disk layout is not"
- " remote_raid1.")
- for disk in instance.disks:
- if disk.iv_name == self.op.disk_name:
- break
- else:
- raise errors.OpPrereqError("Can't find this device ('%s') in the"
- " instance." % self.op.disk_name)
- for child in disk.children:
- if (child.dev_type == constants.LD_DRBD7 and
- child.logical_id[2] == self.op.disk_id):
- break
- else:
- raise errors.OpPrereqError("Can't find the device with this port.")
-
- if len(disk.children) < 2:
- raise errors.OpPrereqError("Cannot remove the last component from"
- " a mirror.")
- self.disk = disk
- self.child = child
- if self.child.logical_id[0] == instance.primary_node:
- oid = 1
- else:
- oid = 0
- self.old_secondary = self.child.logical_id[oid]