4 # Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Google Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 """Logical units dealing with tags."""
26 from ganeti import constants
27 from ganeti import errors
28 from ganeti import locking
29 from ganeti import objects
30 from ganeti import utils
31 from ganeti.cmdlib.base import NoHooksLU
32 from ganeti.cmdlib.common import ExpandNodeName, ExpandInstanceName, ShareAll
35 class TagsLU(NoHooksLU): # pylint: disable=W0223
38 This is an abstract class which is the parent of all the other tags LUs.
41 def ExpandNames(self):
42 self.group_uuid = None
43 self.needed_locks = {}
45 if self.op.kind == constants.TAG_NODE:
46 self.op.name = ExpandNodeName(self.cfg, self.op.name)
47 lock_level = locking.LEVEL_NODE
48 lock_name = self.op.name
49 elif self.op.kind == constants.TAG_INSTANCE:
50 self.op.name = ExpandInstanceName(self.cfg, self.op.name)
51 lock_level = locking.LEVEL_INSTANCE
52 lock_name = self.op.name
53 elif self.op.kind == constants.TAG_NODEGROUP:
54 self.group_uuid = self.cfg.LookupNodeGroup(self.op.name)
55 lock_level = locking.LEVEL_NODEGROUP
56 lock_name = self.group_uuid
57 elif self.op.kind == constants.TAG_NETWORK:
58 self.network_uuid = self.cfg.LookupNetwork(self.op.name)
59 lock_level = locking.LEVEL_NETWORK
60 lock_name = self.network_uuid
65 if lock_level and getattr(self.op, "use_locking", True):
66 self.needed_locks[lock_level] = lock_name
68 # FIXME: Acquire BGL for cluster tag operations (as of this writing it's
69 # not possible to acquire the BGL based on opcode parameters)
71 def CheckPrereq(self):
72 """Check prerequisites.
75 if self.op.kind == constants.TAG_CLUSTER:
76 self.target = self.cfg.GetClusterInfo()
77 elif self.op.kind == constants.TAG_NODE:
78 self.target = self.cfg.GetNodeInfo(self.op.name)
79 elif self.op.kind == constants.TAG_INSTANCE:
80 self.target = self.cfg.GetInstanceInfo(self.op.name)
81 elif self.op.kind == constants.TAG_NODEGROUP:
82 self.target = self.cfg.GetNodeGroup(self.group_uuid)
83 elif self.op.kind == constants.TAG_NETWORK:
84 self.target = self.cfg.GetNetwork(self.network_uuid)
86 raise errors.OpPrereqError("Wrong tag type requested (%s)" %
87 str(self.op.kind), errors.ECODE_INVAL)
90 class LUTagsGet(TagsLU):
91 """Returns the tags of a given object.
96 def ExpandNames(self):
97 TagsLU.ExpandNames(self)
99 # Share locks as this is only a read operation
100 self.share_locks = ShareAll()
102 def Exec(self, feedback_fn):
103 """Returns the tag list.
106 return list(self.target.GetTags())
109 class LUTagsSearch(NoHooksLU):
110 """Searches the tags for a given pattern.
115 def ExpandNames(self):
116 self.needed_locks = {}
118 def CheckPrereq(self):
119 """Check prerequisites.
121 This checks the pattern passed for validity by compiling it.
125 self.re = re.compile(self.op.pattern)
126 except re.error, err:
127 raise errors.OpPrereqError("Invalid search pattern '%s': %s" %
128 (self.op.pattern, err), errors.ECODE_INVAL)
131 def _ExtendTagTargets(targets, object_type_name, object_info_dict):
132 return targets.extend(("/%s/%s" % (object_type_name, o.name), o)
133 for o in object_info_dict.values())
135 def Exec(self, feedback_fn):
136 """Returns the tag list.
140 tgts = [("/cluster", cfg.GetClusterInfo())]
142 LUTagsSearch._ExtendTagTargets(tgts, "instances", cfg.GetAllInstancesInfo())
143 LUTagsSearch._ExtendTagTargets(tgts, "nodes", cfg.GetAllNodesInfo())
144 LUTagsSearch._ExtendTagTargets(tgts, "nodegroup",
145 cfg.GetAllNodeGroupsInfo())
146 LUTagsSearch._ExtendTagTargets(tgts, "network", cfg.GetAllNetworksInfo())
149 for path, target in tgts:
150 for tag in target.GetTags():
151 if self.re.search(tag):
152 results.append((path, tag))
156 class LUTagsSet(TagsLU):
157 """Sets a tag on a given object.
162 def CheckPrereq(self):
163 """Check prerequisites.
165 This checks the type and length of the tag name and value.
168 TagsLU.CheckPrereq(self)
169 for tag in self.op.tags:
170 objects.TaggableObject.ValidateTag(tag)
172 def Exec(self, feedback_fn):
177 for tag in self.op.tags:
178 self.target.AddTag(tag)
179 except errors.TagError, err:
180 raise errors.OpExecError("Error while setting tag: %s" % str(err))
181 self.cfg.Update(self.target, feedback_fn)
184 class LUTagsDel(TagsLU):
185 """Delete a list of tags from a given object.
190 def CheckPrereq(self):
191 """Check prerequisites.
193 This checks that we have the given tag.
196 TagsLU.CheckPrereq(self)
197 for tag in self.op.tags:
198 objects.TaggableObject.ValidateTag(tag)
199 del_tags = frozenset(self.op.tags)
200 cur_tags = self.target.GetTags()
202 diff_tags = del_tags - cur_tags
204 diff_names = ("'%s'" % i for i in sorted(diff_tags))
205 raise errors.OpPrereqError("Tag(s) %s not found" %
206 (utils.CommaJoin(diff_names), ),
209 def Exec(self, feedback_fn):
210 """Remove the tag from the object.
213 for tag in self.op.tags:
214 self.target.RemoveTag(tag)
215 self.cfg.Update(self.target, feedback_fn)