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)
130 def Exec(self, feedback_fn):
131 """Returns the tag list.
135 tgts = [("/cluster", cfg.GetClusterInfo())]
136 ilist = cfg.GetAllInstancesInfo().values()
137 tgts.extend([("/instances/%s" % i.name, i) for i in ilist])
138 nlist = cfg.GetAllNodesInfo().values()
139 tgts.extend([("/nodes/%s" % n.name, n) for n in nlist])
140 tgts.extend(("/nodegroup/%s" % n.name, n)
141 for n in cfg.GetAllNodeGroupsInfo().values())
143 for path, target in tgts:
144 for tag in target.GetTags():
145 if self.re.search(tag):
146 results.append((path, tag))
150 class LUTagsSet(TagsLU):
151 """Sets a tag on a given object.
156 def CheckPrereq(self):
157 """Check prerequisites.
159 This checks the type and length of the tag name and value.
162 TagsLU.CheckPrereq(self)
163 for tag in self.op.tags:
164 objects.TaggableObject.ValidateTag(tag)
166 def Exec(self, feedback_fn):
171 for tag in self.op.tags:
172 self.target.AddTag(tag)
173 except errors.TagError, err:
174 raise errors.OpExecError("Error while setting tag: %s" % str(err))
175 self.cfg.Update(self.target, feedback_fn)
178 class LUTagsDel(TagsLU):
179 """Delete a list of tags from a given object.
184 def CheckPrereq(self):
185 """Check prerequisites.
187 This checks that we have the given tag.
190 TagsLU.CheckPrereq(self)
191 for tag in self.op.tags:
192 objects.TaggableObject.ValidateTag(tag)
193 del_tags = frozenset(self.op.tags)
194 cur_tags = self.target.GetTags()
196 diff_tags = del_tags - cur_tags
198 diff_names = ("'%s'" % i for i in sorted(diff_tags))
199 raise errors.OpPrereqError("Tag(s) %s not found" %
200 (utils.CommaJoin(diff_names), ),
203 def Exec(self, feedback_fn):
204 """Remove the tag from the object.
207 for tag in self.op.tags:
208 self.target.RemoveTag(tag)
209 self.cfg.Update(self.target, feedback_fn)