Group operations: OpCode and LU for removing a group
authorAdeodato Simo <dato@google.com>
Thu, 2 Dec 2010 18:24:40 +0000 (18:24 +0000)
committerAdeodato Simo <dato@google.com>
Wed, 8 Dec 2010 12:27:25 +0000 (12:27 +0000)
Signed-off-by: Adeodato Simo <dato@google.com>
Reviewed-by: Michael Hanselmann <hansmi@google.com>

doc/hooks.rst
lib/cmdlib.py
lib/mcpu.py
lib/opcodes.py

index 3cfd404..9d04a83 100644 (file)
@@ -181,6 +181,18 @@ Adds a node group to the cluster.
 :pre-execution: master node
 :post-execution: master node
 
+OP_REMOVE_GROUP
++++++++++++++++
+
+Removes a node group from the cluster. Since the node group must be
+empty for removal to succeed, the concept of "nodes in the group" does
+not exist, and the hook is only executed in the master node.
+
+:directory: group-remove
+:env. vars: GROUP_NAME
+:pre-execution: master node
+:post-execution: master node
+
 
 Instance operations
 ~~~~~~~~~~~~~~~~~~~
index 24142ec..e28112d 100644 (file)
@@ -10466,6 +10466,73 @@ class LUQueryGroups(NoHooksLU):
     return output
 
 
+class LURemoveGroup(LogicalUnit):
+  HPATH = "group-remove"
+  HTYPE = constants.HTYPE_GROUP
+
+  _OP_PARAMS = [
+    _PGroupName,
+    ]
+
+  REQ_BGL = False
+
+  def ExpandNames(self):
+    # This will raises errors.OpPrereqError on its own:
+    self.group_uuid = self.cfg.LookupNodeGroup(self.op.group_name)
+    self.needed_locks = {
+      locking.LEVEL_NODEGROUP: [self.group_uuid],
+      }
+
+  def CheckPrereq(self):
+    """Check prerequisites.
+
+    This checks that the given group name exists as a node group, that is
+    empty (i.e., contains no nodes), and that is not the last group of the
+    cluster.
+
+    """
+    # Verify that the group is empty.
+    group_nodes = [node.name
+                   for node in self.cfg.GetAllNodesInfo().values()
+                   if node.group == self.group_uuid]
+
+    if group_nodes:
+      raise errors.OpPrereqError("Group '%s' not empty, has the following"
+                                 " nodes: %s" %
+                                 (self.op.group_name,
+                                  utils.CommaJoin(utils.NiceSort(group_nodes))),
+                                 errors.ECODE_STATE)
+
+    # Verify the cluster would not be left group-less.
+    if len(self.cfg.GetNodeGroupList()) == 1:
+      raise errors.OpPrereqError("Group '%s' is the last group in the cluster,"
+                                 " which cannot be left without at least one"
+                                 " group" % self.op.group_name,
+                                 errors.ECODE_STATE)
+
+  def BuildHooksEnv(self):
+    """Build hooks env.
+
+    """
+    env = {
+      "GROUP_NAME": self.op.group_name,
+      }
+    mn = self.cfg.GetMasterNode()
+    return env, [mn], [mn]
+
+  def Exec(self, feedback_fn):
+    """Remove the node group.
+
+    """
+    try:
+      self.cfg.RemoveNodeGroup(self.group_uuid)
+    except errors.ConfigurationError:
+      raise errors.OpExecError("Group '%s' with UUID %s disappeared" %
+                               (self.op.group_name, self.group_uuid))
+
+    self.remove_locks[locking.LEVEL_NODEGROUP] = self.group_uuid
+
+
 class TagsLU(NoHooksLU): # pylint: disable-msg=W0223
   """Generic tags LU.
 
index 436ce28..4dabc6c 100644 (file)
@@ -191,6 +191,7 @@ class Processor(object):
     # node group lu
     opcodes.OpAddGroup: cmdlib.LUAddGroup,
     opcodes.OpQueryGroups: cmdlib.LUQueryGroups,
+    opcodes.OpRemoveGroup: cmdlib.LURemoveGroup,
     # os lu
     opcodes.OpDiagnoseOS: cmdlib.LUDiagnoseOS,
     # exports lu
index 6d0e8aa..a546f1e 100644 (file)
@@ -733,6 +733,13 @@ class OpQueryGroups(OpCode):
   __slots__ = ["output_fields", "names"]
 
 
+class OpRemoveGroup(OpCode):
+  """Remove a node group from the cluster."""
+  OP_ID = "OP_GROUP_REMOVE"
+  OP_DSC_FIELD = "group_name"
+  __slots__ = ["group_name"]
+
+
 # OS opcodes
 class OpDiagnoseOS(OpCode):
   """Compute the list of guest operating systems."""