cmdlib: Cleanup public/private functions
[ganeti-local] / lib / cmdlib / tags.py
1 #
2 #
3
4 # Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Google Inc.
5 #
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.
10 #
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.
15 #
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
19 # 02110-1301, USA.
20
21
22 """Logical units dealing with tags."""
23
24 import re
25
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
33
34
35 class TagsLU(NoHooksLU): # pylint: disable=W0223
36   """Generic tags LU.
37
38   This is an abstract class which is the parent of all the other tags LUs.
39
40   """
41   def ExpandNames(self):
42     self.group_uuid = None
43     self.needed_locks = {}
44
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
61     else:
62       lock_level = None
63       lock_name = None
64
65     if lock_level and getattr(self.op, "use_locking", True):
66       self.needed_locks[lock_level] = lock_name
67
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)
70
71   def CheckPrereq(self):
72     """Check prerequisites.
73
74     """
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)
85     else:
86       raise errors.OpPrereqError("Wrong tag type requested (%s)" %
87                                  str(self.op.kind), errors.ECODE_INVAL)
88
89
90 class LUTagsGet(TagsLU):
91   """Returns the tags of a given object.
92
93   """
94   REQ_BGL = False
95
96   def ExpandNames(self):
97     TagsLU.ExpandNames(self)
98
99     # Share locks as this is only a read operation
100     self.share_locks = ShareAll()
101
102   def Exec(self, feedback_fn):
103     """Returns the tag list.
104
105     """
106     return list(self.target.GetTags())
107
108
109 class LUTagsSearch(NoHooksLU):
110   """Searches the tags for a given pattern.
111
112   """
113   REQ_BGL = False
114
115   def ExpandNames(self):
116     self.needed_locks = {}
117
118   def CheckPrereq(self):
119     """Check prerequisites.
120
121     This checks the pattern passed for validity by compiling it.
122
123     """
124     try:
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)
129
130   def Exec(self, feedback_fn):
131     """Returns the tag list.
132
133     """
134     cfg = self.cfg
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())
142     results = []
143     for path, target in tgts:
144       for tag in target.GetTags():
145         if self.re.search(tag):
146           results.append((path, tag))
147     return results
148
149
150 class LUTagsSet(TagsLU):
151   """Sets a tag on a given object.
152
153   """
154   REQ_BGL = False
155
156   def CheckPrereq(self):
157     """Check prerequisites.
158
159     This checks the type and length of the tag name and value.
160
161     """
162     TagsLU.CheckPrereq(self)
163     for tag in self.op.tags:
164       objects.TaggableObject.ValidateTag(tag)
165
166   def Exec(self, feedback_fn):
167     """Sets the tag.
168
169     """
170     try:
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)
176
177
178 class LUTagsDel(TagsLU):
179   """Delete a list of tags from a given object.
180
181   """
182   REQ_BGL = False
183
184   def CheckPrereq(self):
185     """Check prerequisites.
186
187     This checks that we have the given tag.
188
189     """
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()
195
196     diff_tags = del_tags - cur_tags
197     if diff_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), ),
201                                  errors.ECODE_NOENT)
202
203   def Exec(self, feedback_fn):
204     """Remove the tag from the object.
205
206     """
207     for tag in self.op.tags:
208       self.target.RemoveTag(tag)
209     self.cfg.Update(self.target, feedback_fn)