Statistics
| Branch: | Tag: | Revision:

root / lib / cmdlib / tags.py @ 31d3b918

History | View | Annotate | Download (6.4 kB)

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 ExpandNodeUuidAndName, \
33
  ExpandInstanceUuidAndName, ShareAll
34

    
35

    
36
class TagsLU(NoHooksLU): # pylint: disable=W0223
37
  """Generic tags LU.
38

39
  This is an abstract class which is the parent of all the other tags LUs.
40

41
  """
42
  def ExpandNames(self):
43
    self.group_uuid = None
44
    self.needed_locks = {}
45

    
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
55
      lock_name = inst_name
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
64
    else:
65
      lock_level = None
66
      lock_name = None
67

    
68
    if lock_level and getattr(self.op, "use_locking", True):
69
      self.needed_locks[lock_level] = lock_name
70

    
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)
73

    
74
  def CheckPrereq(self):
75
    """Check prerequisites.
76

77
    """
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)
88
    else:
89
      raise errors.OpPrereqError("Wrong tag type requested (%s)" %
90
                                 str(self.op.kind), errors.ECODE_INVAL)
91

    
92

    
93
class LUTagsGet(TagsLU):
94
  """Returns the tags of a given object.
95

96
  """
97
  REQ_BGL = False
98

    
99
  def ExpandNames(self):
100
    TagsLU.ExpandNames(self)
101

    
102
    # Share locks as this is only a read operation
103
    self.share_locks = ShareAll()
104

    
105
  def Exec(self, feedback_fn):
106
    """Returns the tag list.
107

108
    """
109
    return list(self.target.GetTags())
110

    
111

    
112
class LUTagsSearch(NoHooksLU):
113
  """Searches the tags for a given pattern.
114

115
  """
116
  REQ_BGL = False
117

    
118
  def ExpandNames(self):
119
    self.needed_locks = {}
120

    
121
  def CheckPrereq(self):
122
    """Check prerequisites.
123

124
    This checks the pattern passed for validity by compiling it.
125

126
    """
127
    try:
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)
132

    
133
  @staticmethod
134
  def _ExtendTagTargets(targets, object_type_name, object_info_dict):
135
    return targets.extend(("/%s/%s" % (object_type_name, o.name), o)
136
                          for o in object_info_dict.values())
137

    
138
  def Exec(self, feedback_fn):
139
    """Returns the tag list.
140

141
    """
142
    tgts = [("/cluster", self.cfg.GetClusterInfo())]
143

    
144
    LUTagsSearch._ExtendTagTargets(tgts, "instances",
145
                                   self.cfg.GetAllInstancesInfo())
146
    LUTagsSearch._ExtendTagTargets(tgts, "nodes",
147
                                   self.cfg.GetAllNodesInfo())
148
    LUTagsSearch._ExtendTagTargets(tgts, "nodegroup",
149
                                   self.cfg.GetAllNodeGroupsInfo())
150
    LUTagsSearch._ExtendTagTargets(tgts, "network",
151
                                   self.cfg.GetAllNetworksInfo())
152

    
153
    results = []
154
    for path, target in tgts:
155
      for tag in target.GetTags():
156
        if self.re.search(tag):
157
          results.append((path, tag))
158
    return results
159

    
160

    
161
class LUTagsSet(TagsLU):
162
  """Sets a tag on a given object.
163

164
  """
165
  REQ_BGL = False
166

    
167
  def CheckPrereq(self):
168
    """Check prerequisites.
169

170
    This checks the type and length of the tag name and value.
171

172
    """
173
    TagsLU.CheckPrereq(self)
174
    for tag in self.op.tags:
175
      objects.TaggableObject.ValidateTag(tag)
176

    
177
  def Exec(self, feedback_fn):
178
    """Sets the tag.
179

180
    """
181
    try:
182
      for tag in self.op.tags:
183
        self.target.AddTag(tag)
184
    except errors.TagError, err:
185
      raise errors.OpExecError("Error while setting tag: %s" % str(err))
186
    self.cfg.Update(self.target, feedback_fn)
187

    
188

    
189
class LUTagsDel(TagsLU):
190
  """Delete a list of tags from a given object.
191

192
  """
193
  REQ_BGL = False
194

    
195
  def CheckPrereq(self):
196
    """Check prerequisites.
197

198
    This checks that we have the given tag.
199

200
    """
201
    TagsLU.CheckPrereq(self)
202
    for tag in self.op.tags:
203
      objects.TaggableObject.ValidateTag(tag)
204
    del_tags = frozenset(self.op.tags)
205
    cur_tags = self.target.GetTags()
206

    
207
    diff_tags = del_tags - cur_tags
208
    if diff_tags:
209
      diff_names = ("'%s'" % i for i in sorted(diff_tags))
210
      raise errors.OpPrereqError("Tag(s) %s not found" %
211
                                 (utils.CommaJoin(diff_names), ),
212
                                 errors.ECODE_NOENT)
213

    
214
  def Exec(self, feedback_fn):
215
    """Remove the tag from the object.
216

217
    """
218
    for tag in self.op.tags:
219
      self.target.RemoveTag(tag)
220
    self.cfg.Update(self.target, feedback_fn)