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 ExpandNodeUuidAndName, \
33 ExpandInstanceUuidAndName, ShareAll
36 class TagsLU(NoHooksLU): # pylint: disable=W0223
39 This is an abstract class which is the parent of all the other tags LUs.
42 def ExpandNames(self):
43 self.group_uuid = None
44 self.needed_locks = {}
46 if self.op.kind == constants.TAG_NODE:
47 (self.node_uuid, _) = \
48 ExpandNodeUuidAndName(self.cfg, None, self.op.name)
49 lock_level = locking.LEVEL_NODE
50 lock_name = self.node_uuid
51 elif self.op.kind == constants.TAG_INSTANCE:
52 (self.inst_uuid, inst_name) = \
53 ExpandInstanceUuidAndName(self.cfg, None, self.op.name)
54 lock_level = locking.LEVEL_INSTANCE
56 elif self.op.kind == constants.TAG_NODEGROUP:
57 self.group_uuid = self.cfg.LookupNodeGroup(self.op.name)
58 lock_level = locking.LEVEL_NODEGROUP
59 lock_name = self.group_uuid
60 elif self.op.kind == constants.TAG_NETWORK:
61 self.network_uuid = self.cfg.LookupNetwork(self.op.name)
62 lock_level = locking.LEVEL_NETWORK
63 lock_name = self.network_uuid
68 if lock_level and getattr(self.op, "use_locking", True):
69 self.needed_locks[lock_level] = lock_name
71 # FIXME: Acquire BGL for cluster tag operations (as of this writing it's
72 # not possible to acquire the BGL based on opcode parameters)
74 def CheckPrereq(self):
75 """Check prerequisites.
78 if self.op.kind == constants.TAG_CLUSTER:
79 self.target = self.cfg.GetClusterInfo()
80 elif self.op.kind == constants.TAG_NODE:
81 self.target = self.cfg.GetNodeInfo(self.node_uuid)
82 elif self.op.kind == constants.TAG_INSTANCE:
83 self.target = self.cfg.GetInstanceInfo(self.inst_uuid)
84 elif self.op.kind == constants.TAG_NODEGROUP:
85 self.target = self.cfg.GetNodeGroup(self.group_uuid)
86 elif self.op.kind == constants.TAG_NETWORK:
87 self.target = self.cfg.GetNetwork(self.network_uuid)
89 raise errors.OpPrereqError("Wrong tag type requested (%s)" %
90 str(self.op.kind), errors.ECODE_INVAL)
93 class LUTagsGet(TagsLU):
94 """Returns the tags of a given object.
99 def ExpandNames(self):
100 TagsLU.ExpandNames(self)
102 # Share locks as this is only a read operation
103 self.share_locks = ShareAll()
105 def Exec(self, feedback_fn):
106 """Returns the tag list.
109 return list(self.target.GetTags())
112 class LUTagsSearch(NoHooksLU):
113 """Searches the tags for a given pattern.
118 def ExpandNames(self):
119 self.needed_locks = {}
121 def CheckPrereq(self):
122 """Check prerequisites.
124 This checks the pattern passed for validity by compiling it.
128 self.re = re.compile(self.op.pattern)
129 except re.error, err:
130 raise errors.OpPrereqError("Invalid search pattern '%s': %s" %
131 (self.op.pattern, err), errors.ECODE_INVAL)
133 def Exec(self, feedback_fn):
134 """Returns the tag list.
137 tgts = [("/cluster", self.cfg.GetClusterInfo())]
138 ilist = self.cfg.GetAllInstancesInfo().values()
139 tgts.extend([("/instances/%s" % i.name, i) for i in ilist])
140 nlist = self.cfg.GetAllNodesInfo().values()
141 tgts.extend([("/nodes/%s" % n.name, n) for n in nlist])
142 tgts.extend(("/nodegroup/%s" % n.name, n)
143 for n in self.cfg.GetAllNodeGroupsInfo().values())
145 for path, target in tgts:
146 for tag in target.GetTags():
147 if self.re.search(tag):
148 results.append((path, tag))
152 class LUTagsSet(TagsLU):
153 """Sets a tag on a given object.
158 def CheckPrereq(self):
159 """Check prerequisites.
161 This checks the type and length of the tag name and value.
164 TagsLU.CheckPrereq(self)
165 for tag in self.op.tags:
166 objects.TaggableObject.ValidateTag(tag)
168 def Exec(self, feedback_fn):
173 for tag in self.op.tags:
174 self.target.AddTag(tag)
175 except errors.TagError, err:
176 raise errors.OpExecError("Error while setting tag: %s" % str(err))
177 self.cfg.Update(self.target, feedback_fn)
180 class LUTagsDel(TagsLU):
181 """Delete a list of tags from a given object.
186 def CheckPrereq(self):
187 """Check prerequisites.
189 This checks that we have the given tag.
192 TagsLU.CheckPrereq(self)
193 for tag in self.op.tags:
194 objects.TaggableObject.ValidateTag(tag)
195 del_tags = frozenset(self.op.tags)
196 cur_tags = self.target.GetTags()
198 diff_tags = del_tags - cur_tags
200 diff_names = ("'%s'" % i for i in sorted(diff_tags))
201 raise errors.OpPrereqError("Tag(s) %s not found" %
202 (utils.CommaJoin(diff_names), ),
205 def Exec(self, feedback_fn):
206 """Remove the tag from the object.
209 for tag in self.op.tags:
210 self.target.RemoveTag(tag)
211 self.cfg.Update(self.target, feedback_fn)