Extract tags related logical units from cmdlib
authorThomas Thrainer <thomasth@google.com>
Mon, 13 May 2013 09:16:43 +0000 (11:16 +0200)
committerThomas Thrainer <thomasth@google.com>
Fri, 17 May 2013 09:31:42 +0000 (11:31 +0200)
LUTags* and their base class, TagsLU, are extracted to tags.py. An
additional shared function, _ShareAll, is extracted to common.py for
shared usage.

Signed-off-by: Thomas Thrainer <thomasth@google.com>
Reviewed-by: Bernardo Dal Seno <bdalseno@google.com>

Makefile.am
lib/cmdlib/__init__.py
lib/cmdlib/common.py
lib/cmdlib/tags.py [new file with mode: 0644]

index db39e7e..35d1e5d 100644 (file)
@@ -310,7 +310,8 @@ client_PYTHON = \
 cmdlib_PYTHON = \
        lib/cmdlib/__init__.py \
        lib/cmdlib/common.py \
-       lib/cmdlib/base.py
+       lib/cmdlib/base.py \
+       lib/cmdlib/tags.py
 
 hypervisor_PYTHON = \
        lib/hypervisor/__init__.py \
index 0166528..c3148af 100644 (file)
@@ -66,7 +66,8 @@ from ganeti.masterd import iallocator
 from ganeti.cmdlib.base import ResultWithJobs, LogicalUnit, NoHooksLU, \
   Tasklet, _QueryBase
 from ganeti.cmdlib.common import _ExpandInstanceName, _ExpandItemName, \
-  _ExpandNodeName
+  _ExpandNodeName, _ShareAll
+from ganeti.cmdlib.tags import LUTagsGet, LUTagsSearch, LUTagsSet, LUTagsDel
 
 import ganeti.masterd.instance # pylint: disable=W0611
 
@@ -82,13 +83,6 @@ CAN_CHANGE_INSTANCE_OFFLINE = (frozenset(INSTANCE_DOWN) | frozenset([
   ]))
 
 
-def _ShareAll():
-  """Returns a dict declaring all lock levels shared.
-
-  """
-  return dict.fromkeys(locking.LEVELS, 1)
-
-
 def _AnnotateDiskParams(instance, devs, cfg):
   """Little helper wrapper to the rpc annotation method.
 
@@ -15377,183 +15371,6 @@ class LUGroupEvacuate(LogicalUnit):
     return ResultWithJobs(jobs)
 
 
-class TagsLU(NoHooksLU): # pylint: disable=W0223
-  """Generic tags LU.
-
-  This is an abstract class which is the parent of all the other tags LUs.
-
-  """
-  def ExpandNames(self):
-    self.group_uuid = None
-    self.needed_locks = {}
-
-    if self.op.kind == constants.TAG_NODE:
-      self.op.name = _ExpandNodeName(self.cfg, self.op.name)
-      lock_level = locking.LEVEL_NODE
-      lock_name = self.op.name
-    elif self.op.kind == constants.TAG_INSTANCE:
-      self.op.name = _ExpandInstanceName(self.cfg, self.op.name)
-      lock_level = locking.LEVEL_INSTANCE
-      lock_name = self.op.name
-    elif self.op.kind == constants.TAG_NODEGROUP:
-      self.group_uuid = self.cfg.LookupNodeGroup(self.op.name)
-      lock_level = locking.LEVEL_NODEGROUP
-      lock_name = self.group_uuid
-    elif self.op.kind == constants.TAG_NETWORK:
-      self.network_uuid = self.cfg.LookupNetwork(self.op.name)
-      lock_level = locking.LEVEL_NETWORK
-      lock_name = self.network_uuid
-    else:
-      lock_level = None
-      lock_name = None
-
-    if lock_level and getattr(self.op, "use_locking", True):
-      self.needed_locks[lock_level] = lock_name
-
-    # FIXME: Acquire BGL for cluster tag operations (as of this writing it's
-    # not possible to acquire the BGL based on opcode parameters)
-
-  def CheckPrereq(self):
-    """Check prerequisites.
-
-    """
-    if self.op.kind == constants.TAG_CLUSTER:
-      self.target = self.cfg.GetClusterInfo()
-    elif self.op.kind == constants.TAG_NODE:
-      self.target = self.cfg.GetNodeInfo(self.op.name)
-    elif self.op.kind == constants.TAG_INSTANCE:
-      self.target = self.cfg.GetInstanceInfo(self.op.name)
-    elif self.op.kind == constants.TAG_NODEGROUP:
-      self.target = self.cfg.GetNodeGroup(self.group_uuid)
-    elif self.op.kind == constants.TAG_NETWORK:
-      self.target = self.cfg.GetNetwork(self.network_uuid)
-    else:
-      raise errors.OpPrereqError("Wrong tag type requested (%s)" %
-                                 str(self.op.kind), errors.ECODE_INVAL)
-
-
-class LUTagsGet(TagsLU):
-  """Returns the tags of a given object.
-
-  """
-  REQ_BGL = False
-
-  def ExpandNames(self):
-    TagsLU.ExpandNames(self)
-
-    # Share locks as this is only a read operation
-    self.share_locks = _ShareAll()
-
-  def Exec(self, feedback_fn):
-    """Returns the tag list.
-
-    """
-    return list(self.target.GetTags())
-
-
-class LUTagsSearch(NoHooksLU):
-  """Searches the tags for a given pattern.
-
-  """
-  REQ_BGL = False
-
-  def ExpandNames(self):
-    self.needed_locks = {}
-
-  def CheckPrereq(self):
-    """Check prerequisites.
-
-    This checks the pattern passed for validity by compiling it.
-
-    """
-    try:
-      self.re = re.compile(self.op.pattern)
-    except re.error, err:
-      raise errors.OpPrereqError("Invalid search pattern '%s': %s" %
-                                 (self.op.pattern, err), errors.ECODE_INVAL)
-
-  def Exec(self, feedback_fn):
-    """Returns the tag list.
-
-    """
-    cfg = self.cfg
-    tgts = [("/cluster", cfg.GetClusterInfo())]
-    ilist = cfg.GetAllInstancesInfo().values()
-    tgts.extend([("/instances/%s" % i.name, i) for i in ilist])
-    nlist = cfg.GetAllNodesInfo().values()
-    tgts.extend([("/nodes/%s" % n.name, n) for n in nlist])
-    tgts.extend(("/nodegroup/%s" % n.name, n)
-                for n in cfg.GetAllNodeGroupsInfo().values())
-    results = []
-    for path, target in tgts:
-      for tag in target.GetTags():
-        if self.re.search(tag):
-          results.append((path, tag))
-    return results
-
-
-class LUTagsSet(TagsLU):
-  """Sets a tag on a given object.
-
-  """
-  REQ_BGL = False
-
-  def CheckPrereq(self):
-    """Check prerequisites.
-
-    This checks the type and length of the tag name and value.
-
-    """
-    TagsLU.CheckPrereq(self)
-    for tag in self.op.tags:
-      objects.TaggableObject.ValidateTag(tag)
-
-  def Exec(self, feedback_fn):
-    """Sets the tag.
-
-    """
-    try:
-      for tag in self.op.tags:
-        self.target.AddTag(tag)
-    except errors.TagError, err:
-      raise errors.OpExecError("Error while setting tag: %s" % str(err))
-    self.cfg.Update(self.target, feedback_fn)
-
-
-class LUTagsDel(TagsLU):
-  """Delete a list of tags from a given object.
-
-  """
-  REQ_BGL = False
-
-  def CheckPrereq(self):
-    """Check prerequisites.
-
-    This checks that we have the given tag.
-
-    """
-    TagsLU.CheckPrereq(self)
-    for tag in self.op.tags:
-      objects.TaggableObject.ValidateTag(tag)
-    del_tags = frozenset(self.op.tags)
-    cur_tags = self.target.GetTags()
-
-    diff_tags = del_tags - cur_tags
-    if diff_tags:
-      diff_names = ("'%s'" % i for i in sorted(diff_tags))
-      raise errors.OpPrereqError("Tag(s) %s not found" %
-                                 (utils.CommaJoin(diff_names), ),
-                                 errors.ECODE_NOENT)
-
-  def Exec(self, feedback_fn):
-    """Remove the tag from the object.
-
-    """
-    for tag in self.op.tags:
-      self.target.RemoveTag(tag)
-    self.cfg.Update(self.target, feedback_fn)
-
-
 class LUTestDelay(NoHooksLU):
   """Sleep for a specified amount of time.
 
index f565a0e..60d5fe5 100644 (file)
@@ -22,6 +22,7 @@
 """Common functions used by multiple logical units."""
 
 from ganeti import errors
+from ganeti import locking
 
 
 def _ExpandItemName(fn, name, kind):
@@ -49,3 +50,10 @@ def _ExpandInstanceName(cfg, name):
 def _ExpandNodeName(cfg, name):
   """Wrapper over L{_ExpandItemName} for nodes."""
   return _ExpandItemName(cfg.ExpandNodeName, name, "Node")
+
+
+def _ShareAll():
+  """Returns a dict declaring all lock levels shared.
+
+  """
+  return dict.fromkeys(locking.LEVELS, 1)
diff --git a/lib/cmdlib/tags.py b/lib/cmdlib/tags.py
new file mode 100644 (file)
index 0000000..0ec27a6
--- /dev/null
@@ -0,0 +1,210 @@
+#
+#
+
+# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Google Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+
+"""Logical units dealing with tags."""
+
+import re
+
+from ganeti import constants
+from ganeti import errors
+from ganeti import locking
+from ganeti import objects
+from ganeti import utils
+from ganeti.cmdlib.base import NoHooksLU
+from ganeti.cmdlib.common import _ExpandNodeName, _ExpandInstanceName, \
+  _ShareAll
+
+
+class TagsLU(NoHooksLU): # pylint: disable=W0223
+  """Generic tags LU.
+
+  This is an abstract class which is the parent of all the other tags LUs.
+
+  """
+  def ExpandNames(self):
+    self.group_uuid = None
+    self.needed_locks = {}
+
+    if self.op.kind == constants.TAG_NODE:
+      self.op.name = _ExpandNodeName(self.cfg, self.op.name)
+      lock_level = locking.LEVEL_NODE
+      lock_name = self.op.name
+    elif self.op.kind == constants.TAG_INSTANCE:
+      self.op.name = _ExpandInstanceName(self.cfg, self.op.name)
+      lock_level = locking.LEVEL_INSTANCE
+      lock_name = self.op.name
+    elif self.op.kind == constants.TAG_NODEGROUP:
+      self.group_uuid = self.cfg.LookupNodeGroup(self.op.name)
+      lock_level = locking.LEVEL_NODEGROUP
+      lock_name = self.group_uuid
+    elif self.op.kind == constants.TAG_NETWORK:
+      self.network_uuid = self.cfg.LookupNetwork(self.op.name)
+      lock_level = locking.LEVEL_NETWORK
+      lock_name = self.network_uuid
+    else:
+      lock_level = None
+      lock_name = None
+
+    if lock_level and getattr(self.op, "use_locking", True):
+      self.needed_locks[lock_level] = lock_name
+
+    # FIXME: Acquire BGL for cluster tag operations (as of this writing it's
+    # not possible to acquire the BGL based on opcode parameters)
+
+  def CheckPrereq(self):
+    """Check prerequisites.
+
+    """
+    if self.op.kind == constants.TAG_CLUSTER:
+      self.target = self.cfg.GetClusterInfo()
+    elif self.op.kind == constants.TAG_NODE:
+      self.target = self.cfg.GetNodeInfo(self.op.name)
+    elif self.op.kind == constants.TAG_INSTANCE:
+      self.target = self.cfg.GetInstanceInfo(self.op.name)
+    elif self.op.kind == constants.TAG_NODEGROUP:
+      self.target = self.cfg.GetNodeGroup(self.group_uuid)
+    elif self.op.kind == constants.TAG_NETWORK:
+      self.target = self.cfg.GetNetwork(self.network_uuid)
+    else:
+      raise errors.OpPrereqError("Wrong tag type requested (%s)" %
+                                 str(self.op.kind), errors.ECODE_INVAL)
+
+
+class LUTagsGet(TagsLU):
+  """Returns the tags of a given object.
+
+  """
+  REQ_BGL = False
+
+  def ExpandNames(self):
+    TagsLU.ExpandNames(self)
+
+    # Share locks as this is only a read operation
+    self.share_locks = _ShareAll()
+
+  def Exec(self, feedback_fn):
+    """Returns the tag list.
+
+    """
+    return list(self.target.GetTags())
+
+
+class LUTagsSearch(NoHooksLU):
+  """Searches the tags for a given pattern.
+
+  """
+  REQ_BGL = False
+
+  def ExpandNames(self):
+    self.needed_locks = {}
+
+  def CheckPrereq(self):
+    """Check prerequisites.
+
+    This checks the pattern passed for validity by compiling it.
+
+    """
+    try:
+      self.re = re.compile(self.op.pattern)
+    except re.error, err:
+      raise errors.OpPrereqError("Invalid search pattern '%s': %s" %
+                                 (self.op.pattern, err), errors.ECODE_INVAL)
+
+  def Exec(self, feedback_fn):
+    """Returns the tag list.
+
+    """
+    cfg = self.cfg
+    tgts = [("/cluster", cfg.GetClusterInfo())]
+    ilist = cfg.GetAllInstancesInfo().values()
+    tgts.extend([("/instances/%s" % i.name, i) for i in ilist])
+    nlist = cfg.GetAllNodesInfo().values()
+    tgts.extend([("/nodes/%s" % n.name, n) for n in nlist])
+    tgts.extend(("/nodegroup/%s" % n.name, n)
+                for n in cfg.GetAllNodeGroupsInfo().values())
+    results = []
+    for path, target in tgts:
+      for tag in target.GetTags():
+        if self.re.search(tag):
+          results.append((path, tag))
+    return results
+
+
+class LUTagsSet(TagsLU):
+  """Sets a tag on a given object.
+
+  """
+  REQ_BGL = False
+
+  def CheckPrereq(self):
+    """Check prerequisites.
+
+    This checks the type and length of the tag name and value.
+
+    """
+    TagsLU.CheckPrereq(self)
+    for tag in self.op.tags:
+      objects.TaggableObject.ValidateTag(tag)
+
+  def Exec(self, feedback_fn):
+    """Sets the tag.
+
+    """
+    try:
+      for tag in self.op.tags:
+        self.target.AddTag(tag)
+    except errors.TagError, err:
+      raise errors.OpExecError("Error while setting tag: %s" % str(err))
+    self.cfg.Update(self.target, feedback_fn)
+
+
+class LUTagsDel(TagsLU):
+  """Delete a list of tags from a given object.
+
+  """
+  REQ_BGL = False
+
+  def CheckPrereq(self):
+    """Check prerequisites.
+
+    This checks that we have the given tag.
+
+    """
+    TagsLU.CheckPrereq(self)
+    for tag in self.op.tags:
+      objects.TaggableObject.ValidateTag(tag)
+    del_tags = frozenset(self.op.tags)
+    cur_tags = self.target.GetTags()
+
+    diff_tags = del_tags - cur_tags
+    if diff_tags:
+      diff_names = ("'%s'" % i for i in sorted(diff_tags))
+      raise errors.OpPrereqError("Tag(s) %s not found" %
+                                 (utils.CommaJoin(diff_names), ),
+                                 errors.ECODE_NOENT)
+
+  def Exec(self, feedback_fn):
+    """Remove the tag from the object.
+
+    """
+    for tag in self.op.tags:
+      self.target.RemoveTag(tag)
+    self.cfg.Update(self.target, feedback_fn)