From 94bd652a740636073afe7392d04752c96b2c076a Mon Sep 17 00:00:00 2001
From: Adeodato Simo <dato@google.com>
Date: Thu, 2 Dec 2010 18:24:40 +0000
Subject: [PATCH] Group operations: OpCode and LU for removing a group

Signed-off-by: Adeodato Simo <dato@google.com>
Reviewed-by: Michael Hanselmann <hansmi@google.com>
---
 doc/hooks.rst  | 12 +++++++++
 lib/cmdlib.py  | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/mcpu.py    |  1 +
 lib/opcodes.py |  7 ++++++
 4 files changed, 87 insertions(+)

diff --git a/doc/hooks.rst b/doc/hooks.rst
index 3cfd40498..9d04a839c 100644
--- a/doc/hooks.rst
+++ b/doc/hooks.rst
@@ -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
 ~~~~~~~~~~~~~~~~~~~
diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index 24142ece9..e28112d3a 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -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.
 
diff --git a/lib/mcpu.py b/lib/mcpu.py
index 436ce28ca..4dabc6c6a 100644
--- a/lib/mcpu.py
+++ b/lib/mcpu.py
@@ -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
diff --git a/lib/opcodes.py b/lib/opcodes.py
index 6d0e8aaf0..a546f1e53 100644
--- a/lib/opcodes.py
+++ b/lib/opcodes.py
@@ -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."""
-- 
GitLab