Statistics
| Branch: | Tag: | Revision:

root / lib / objects.py @ 061af273

History | View | Annotate | Download (44.5 kB)

1 2f31098c Iustin Pop
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 6d33a6eb Iustin Pop
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Google Inc.
5 a8083063 Iustin Pop
#
6 a8083063 Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 a8083063 Iustin Pop
# it under the terms of the GNU General Public License as published by
8 a8083063 Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 a8083063 Iustin Pop
# (at your option) any later version.
10 a8083063 Iustin Pop
#
11 a8083063 Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 a8083063 Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 a8083063 Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 a8083063 Iustin Pop
# General Public License for more details.
15 a8083063 Iustin Pop
#
16 a8083063 Iustin Pop
# You should have received a copy of the GNU General Public License
17 a8083063 Iustin Pop
# along with this program; if not, write to the Free Software
18 a8083063 Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 a8083063 Iustin Pop
# 02110-1301, USA.
20 a8083063 Iustin Pop
21 a8083063 Iustin Pop
22 a8083063 Iustin Pop
"""Transportable objects for Ganeti.
23 a8083063 Iustin Pop

24 a8083063 Iustin Pop
This module provides small, mostly data-only objects which are safe to
25 a8083063 Iustin Pop
pass to and from external parties.
26 a8083063 Iustin Pop

27 a8083063 Iustin Pop
"""
28 a8083063 Iustin Pop
29 b459a848 Andrea Spadaccini
# pylint: disable=E0203,W0201
30 6c881c52 Iustin Pop
31 6c881c52 Iustin Pop
# E0203: Access to member %r before its definition, since we use
32 6c881c52 Iustin Pop
# objects.py which doesn't explicitely initialise its members
33 6c881c52 Iustin Pop
34 7260cfbe Iustin Pop
# W0201: Attribute '%s' defined outside __init__
35 a8083063 Iustin Pop
36 a8083063 Iustin Pop
import ConfigParser
37 5c947f38 Iustin Pop
import re
38 5bf7b5cf Iustin Pop
import copy
39 e11a1b77 Adeodato Simo
import time
40 d5835922 Michael Hanselmann
from cStringIO import StringIO
41 a8083063 Iustin Pop
42 a8083063 Iustin Pop
from ganeti import errors
43 5c947f38 Iustin Pop
from ganeti import constants
44 a8083063 Iustin Pop
45 f4c9af7a Guido Trotter
from socket import AF_INET
46 f4c9af7a Guido Trotter
47 a8083063 Iustin Pop
48 a8083063 Iustin Pop
__all__ = ["ConfigObject", "ConfigData", "NIC", "Disk", "Instance",
49 24a3707f Guido Trotter
           "OS", "Node", "NodeGroup", "Cluster", "FillDict"]
50 a8083063 Iustin Pop
51 d693c864 Iustin Pop
_TIMESTAMPS = ["ctime", "mtime"]
52 e1dcc53a Iustin Pop
_UUID = ["uuid"]
53 96acbc09 Michael Hanselmann
54 8d8d650c Michael Hanselmann
55 e11ddf13 Iustin Pop
def FillDict(defaults_dict, custom_dict, skip_keys=None):
56 29921401 Iustin Pop
  """Basic function to apply settings on top a default dict.
57 abe609b2 Guido Trotter

58 29921401 Iustin Pop
  @type defaults_dict: dict
59 29921401 Iustin Pop
  @param defaults_dict: dictionary holding the default values
60 29921401 Iustin Pop
  @type custom_dict: dict
61 29921401 Iustin Pop
  @param custom_dict: dictionary holding customized value
62 7736a5f2 Iustin Pop
  @type skip_keys: list
63 7736a5f2 Iustin Pop
  @param skip_keys: which keys not to fill
64 29921401 Iustin Pop
  @rtype: dict
65 29921401 Iustin Pop
  @return: dict with the 'full' values
66 abe609b2 Guido Trotter

67 29921401 Iustin Pop
  """
68 29921401 Iustin Pop
  ret_dict = copy.deepcopy(defaults_dict)
69 29921401 Iustin Pop
  ret_dict.update(custom_dict)
70 e11ddf13 Iustin Pop
  if skip_keys:
71 e11ddf13 Iustin Pop
    for k in skip_keys:
72 e11ddf13 Iustin Pop
      try:
73 e11ddf13 Iustin Pop
        del ret_dict[k]
74 e11ddf13 Iustin Pop
      except KeyError:
75 e11ddf13 Iustin Pop
        pass
76 29921401 Iustin Pop
  return ret_dict
77 a8083063 Iustin Pop
78 6e34b628 Guido Trotter
79 6e34b628 Guido Trotter
def UpgradeGroupedParams(target, defaults):
80 6e34b628 Guido Trotter
  """Update all groups for the target parameter.
81 6e34b628 Guido Trotter

82 6e34b628 Guido Trotter
  @type target: dict of dicts
83 6e34b628 Guido Trotter
  @param target: {group: {parameter: value}}
84 6e34b628 Guido Trotter
  @type defaults: dict
85 6e34b628 Guido Trotter
  @param defaults: default parameter values
86 6e34b628 Guido Trotter

87 6e34b628 Guido Trotter
  """
88 6e34b628 Guido Trotter
  if target is None:
89 6e34b628 Guido Trotter
    target = {constants.PP_DEFAULT: defaults}
90 6e34b628 Guido Trotter
  else:
91 6e34b628 Guido Trotter
    for group in target:
92 6e34b628 Guido Trotter
      target[group] = FillDict(defaults, target[group])
93 6e34b628 Guido Trotter
  return target
94 6e34b628 Guido Trotter
95 6e34b628 Guido Trotter
96 a8083063 Iustin Pop
class ConfigObject(object):
97 a8083063 Iustin Pop
  """A generic config object.
98 a8083063 Iustin Pop

99 a8083063 Iustin Pop
  It has the following properties:
100 a8083063 Iustin Pop

101 a8083063 Iustin Pop
    - provides somewhat safe recursive unpickling and pickling for its classes
102 a8083063 Iustin Pop
    - unset attributes which are defined in slots are always returned
103 a8083063 Iustin Pop
      as None instead of raising an error
104 a8083063 Iustin Pop

105 a8083063 Iustin Pop
  Classes derived from this must always declare __slots__ (we use many
106 55224070 Guido Trotter
  config objects and the memory reduction is useful)
107 a8083063 Iustin Pop

108 a8083063 Iustin Pop
  """
109 a8083063 Iustin Pop
  __slots__ = []
110 a8083063 Iustin Pop
111 a8083063 Iustin Pop
  def __init__(self, **kwargs):
112 319856a9 Michael Hanselmann
    for k, v in kwargs.iteritems():
113 319856a9 Michael Hanselmann
      setattr(self, k, v)
114 a8083063 Iustin Pop
115 a8083063 Iustin Pop
  def __getattr__(self, name):
116 adf385c7 Iustin Pop
    if name not in self._all_slots():
117 3ecf6786 Iustin Pop
      raise AttributeError("Invalid object attribute %s.%s" %
118 3ecf6786 Iustin Pop
                           (type(self).__name__, name))
119 a8083063 Iustin Pop
    return None
120 a8083063 Iustin Pop
121 a8083063 Iustin Pop
  def __setstate__(self, state):
122 adf385c7 Iustin Pop
    slots = self._all_slots()
123 a8083063 Iustin Pop
    for name in state:
124 adf385c7 Iustin Pop
      if name in slots:
125 a8083063 Iustin Pop
        setattr(self, name, state[name])
126 a8083063 Iustin Pop
127 adf385c7 Iustin Pop
  @classmethod
128 adf385c7 Iustin Pop
  def _all_slots(cls):
129 adf385c7 Iustin Pop
    """Compute the list of all declared slots for a class.
130 adf385c7 Iustin Pop

131 adf385c7 Iustin Pop
    """
132 adf385c7 Iustin Pop
    slots = []
133 adf385c7 Iustin Pop
    for parent in cls.__mro__:
134 adf385c7 Iustin Pop
      slots.extend(getattr(parent, "__slots__", []))
135 adf385c7 Iustin Pop
    return slots
136 adf385c7 Iustin Pop
137 ff9c047c Iustin Pop
  def ToDict(self):
138 ff9c047c Iustin Pop
    """Convert to a dict holding only standard python types.
139 ff9c047c Iustin Pop

140 ff9c047c Iustin Pop
    The generic routine just dumps all of this object's attributes in
141 ff9c047c Iustin Pop
    a dict. It does not work if the class has children who are
142 ff9c047c Iustin Pop
    ConfigObjects themselves (e.g. the nics list in an Instance), in
143 ff9c047c Iustin Pop
    which case the object should subclass the function in order to
144 ff9c047c Iustin Pop
    make sure all objects returned are only standard python types.
145 ff9c047c Iustin Pop

146 ff9c047c Iustin Pop
    """
147 4c14965f Guido Trotter
    result = {}
148 adf385c7 Iustin Pop
    for name in self._all_slots():
149 4c14965f Guido Trotter
      value = getattr(self, name, None)
150 4c14965f Guido Trotter
      if value is not None:
151 4c14965f Guido Trotter
        result[name] = value
152 4c14965f Guido Trotter
    return result
153 4c14965f Guido Trotter
154 4c14965f Guido Trotter
  __getstate__ = ToDict
155 ff9c047c Iustin Pop
156 ff9c047c Iustin Pop
  @classmethod
157 ff9c047c Iustin Pop
  def FromDict(cls, val):
158 ff9c047c Iustin Pop
    """Create an object from a dictionary.
159 ff9c047c Iustin Pop

160 ff9c047c Iustin Pop
    This generic routine takes a dict, instantiates a new instance of
161 ff9c047c Iustin Pop
    the given class, and sets attributes based on the dict content.
162 ff9c047c Iustin Pop

163 ff9c047c Iustin Pop
    As for `ToDict`, this does not work if the class has children
164 ff9c047c Iustin Pop
    who are ConfigObjects themselves (e.g. the nics list in an
165 ff9c047c Iustin Pop
    Instance), in which case the object should subclass the function
166 ff9c047c Iustin Pop
    and alter the objects.
167 ff9c047c Iustin Pop

168 ff9c047c Iustin Pop
    """
169 ff9c047c Iustin Pop
    if not isinstance(val, dict):
170 ff9c047c Iustin Pop
      raise errors.ConfigurationError("Invalid object passed to FromDict:"
171 ff9c047c Iustin Pop
                                      " expected dict, got %s" % type(val))
172 319856a9 Michael Hanselmann
    val_str = dict([(str(k), v) for k, v in val.iteritems()])
173 b459a848 Andrea Spadaccini
    obj = cls(**val_str) # pylint: disable=W0142
174 ff9c047c Iustin Pop
    return obj
175 ff9c047c Iustin Pop
176 ff9c047c Iustin Pop
  @staticmethod
177 ff9c047c Iustin Pop
  def _ContainerToDicts(container):
178 ff9c047c Iustin Pop
    """Convert the elements of a container to standard python types.
179 ff9c047c Iustin Pop

180 ff9c047c Iustin Pop
    This method converts a container with elements derived from
181 ff9c047c Iustin Pop
    ConfigData to standard python types. If the container is a dict,
182 ff9c047c Iustin Pop
    we don't touch the keys, only the values.
183 ff9c047c Iustin Pop

184 ff9c047c Iustin Pop
    """
185 ff9c047c Iustin Pop
    if isinstance(container, dict):
186 ff9c047c Iustin Pop
      ret = dict([(k, v.ToDict()) for k, v in container.iteritems()])
187 ff9c047c Iustin Pop
    elif isinstance(container, (list, tuple, set, frozenset)):
188 ff9c047c Iustin Pop
      ret = [elem.ToDict() for elem in container]
189 ff9c047c Iustin Pop
    else:
190 ff9c047c Iustin Pop
      raise TypeError("Invalid type %s passed to _ContainerToDicts" %
191 ff9c047c Iustin Pop
                      type(container))
192 ff9c047c Iustin Pop
    return ret
193 ff9c047c Iustin Pop
194 ff9c047c Iustin Pop
  @staticmethod
195 ff9c047c Iustin Pop
  def _ContainerFromDicts(source, c_type, e_type):
196 ff9c047c Iustin Pop
    """Convert a container from standard python types.
197 ff9c047c Iustin Pop

198 ff9c047c Iustin Pop
    This method converts a container with standard python types to
199 ff9c047c Iustin Pop
    ConfigData objects. If the container is a dict, we don't touch the
200 ff9c047c Iustin Pop
    keys, only the values.
201 ff9c047c Iustin Pop

202 ff9c047c Iustin Pop
    """
203 ff9c047c Iustin Pop
    if not isinstance(c_type, type):
204 ff9c047c Iustin Pop
      raise TypeError("Container type %s passed to _ContainerFromDicts is"
205 ff9c047c Iustin Pop
                      " not a type" % type(c_type))
206 fe25a79a Guido Trotter
    if source is None:
207 fe25a79a Guido Trotter
      source = c_type()
208 ff9c047c Iustin Pop
    if c_type is dict:
209 ff9c047c Iustin Pop
      ret = dict([(k, e_type.FromDict(v)) for k, v in source.iteritems()])
210 ff9c047c Iustin Pop
    elif c_type in (list, tuple, set, frozenset):
211 ff9c047c Iustin Pop
      ret = c_type([e_type.FromDict(elem) for elem in source])
212 ff9c047c Iustin Pop
    else:
213 ff9c047c Iustin Pop
      raise TypeError("Invalid container type %s passed to"
214 ff9c047c Iustin Pop
                      " _ContainerFromDicts" % c_type)
215 ff9c047c Iustin Pop
    return ret
216 ff9c047c Iustin Pop
217 e8d563f3 Iustin Pop
  def Copy(self):
218 e8d563f3 Iustin Pop
    """Makes a deep copy of the current object and its children.
219 e8d563f3 Iustin Pop

220 e8d563f3 Iustin Pop
    """
221 e8d563f3 Iustin Pop
    dict_form = self.ToDict()
222 e8d563f3 Iustin Pop
    clone_obj = self.__class__.FromDict(dict_form)
223 e8d563f3 Iustin Pop
    return clone_obj
224 e8d563f3 Iustin Pop
225 ff9c047c Iustin Pop
  def __repr__(self):
226 ff9c047c Iustin Pop
    """Implement __repr__ for ConfigObjects."""
227 ff9c047c Iustin Pop
    return repr(self.ToDict())
228 ff9c047c Iustin Pop
229 560428be Guido Trotter
  def UpgradeConfig(self):
230 560428be Guido Trotter
    """Fill defaults for missing configuration values.
231 560428be Guido Trotter

232 90d726a8 Iustin Pop
    This method will be called at configuration load time, and its
233 90d726a8 Iustin Pop
    implementation will be object dependent.
234 560428be Guido Trotter

235 560428be Guido Trotter
    """
236 560428be Guido Trotter
    pass
237 560428be Guido Trotter
238 a8083063 Iustin Pop
239 ec29fe40 Iustin Pop
class TaggableObject(ConfigObject):
240 5c947f38 Iustin Pop
  """An generic class supporting tags.
241 5c947f38 Iustin Pop

242 5c947f38 Iustin Pop
  """
243 154b9580 Balazs Lecz
  __slots__ = ["tags"]
244 b5e5632e Iustin Pop
  VALID_TAG_RE = re.compile("^[\w.+*/:@-]+$")
245 2057f6c7 Iustin Pop
246 b5e5632e Iustin Pop
  @classmethod
247 b5e5632e Iustin Pop
  def ValidateTag(cls, tag):
248 5c947f38 Iustin Pop
    """Check if a tag is valid.
249 5c947f38 Iustin Pop

250 5c947f38 Iustin Pop
    If the tag is invalid, an errors.TagError will be raised. The
251 5c947f38 Iustin Pop
    function has no return value.
252 5c947f38 Iustin Pop

253 5c947f38 Iustin Pop
    """
254 5c947f38 Iustin Pop
    if not isinstance(tag, basestring):
255 3ecf6786 Iustin Pop
      raise errors.TagError("Invalid tag type (not a string)")
256 5c947f38 Iustin Pop
    if len(tag) > constants.MAX_TAG_LEN:
257 319856a9 Michael Hanselmann
      raise errors.TagError("Tag too long (>%d characters)" %
258 319856a9 Michael Hanselmann
                            constants.MAX_TAG_LEN)
259 5c947f38 Iustin Pop
    if not tag:
260 3ecf6786 Iustin Pop
      raise errors.TagError("Tags cannot be empty")
261 b5e5632e Iustin Pop
    if not cls.VALID_TAG_RE.match(tag):
262 3ecf6786 Iustin Pop
      raise errors.TagError("Tag contains invalid characters")
263 5c947f38 Iustin Pop
264 5c947f38 Iustin Pop
  def GetTags(self):
265 5c947f38 Iustin Pop
    """Return the tags list.
266 5c947f38 Iustin Pop

267 5c947f38 Iustin Pop
    """
268 5c947f38 Iustin Pop
    tags = getattr(self, "tags", None)
269 5c947f38 Iustin Pop
    if tags is None:
270 5c947f38 Iustin Pop
      tags = self.tags = set()
271 5c947f38 Iustin Pop
    return tags
272 5c947f38 Iustin Pop
273 5c947f38 Iustin Pop
  def AddTag(self, tag):
274 5c947f38 Iustin Pop
    """Add a new tag.
275 5c947f38 Iustin Pop

276 5c947f38 Iustin Pop
    """
277 5c947f38 Iustin Pop
    self.ValidateTag(tag)
278 5c947f38 Iustin Pop
    tags = self.GetTags()
279 5c947f38 Iustin Pop
    if len(tags) >= constants.MAX_TAGS_PER_OBJ:
280 3ecf6786 Iustin Pop
      raise errors.TagError("Too many tags")
281 5c947f38 Iustin Pop
    self.GetTags().add(tag)
282 5c947f38 Iustin Pop
283 5c947f38 Iustin Pop
  def RemoveTag(self, tag):
284 5c947f38 Iustin Pop
    """Remove a tag.
285 5c947f38 Iustin Pop

286 5c947f38 Iustin Pop
    """
287 5c947f38 Iustin Pop
    self.ValidateTag(tag)
288 5c947f38 Iustin Pop
    tags = self.GetTags()
289 5c947f38 Iustin Pop
    try:
290 5c947f38 Iustin Pop
      tags.remove(tag)
291 5c947f38 Iustin Pop
    except KeyError:
292 3ecf6786 Iustin Pop
      raise errors.TagError("Tag not found")
293 5c947f38 Iustin Pop
294 ff9c047c Iustin Pop
  def ToDict(self):
295 ff9c047c Iustin Pop
    """Taggable-object-specific conversion to standard python types.
296 ff9c047c Iustin Pop

297 ff9c047c Iustin Pop
    This replaces the tags set with a list.
298 ff9c047c Iustin Pop

299 ff9c047c Iustin Pop
    """
300 ff9c047c Iustin Pop
    bo = super(TaggableObject, self).ToDict()
301 ff9c047c Iustin Pop
302 ff9c047c Iustin Pop
    tags = bo.get("tags", None)
303 ff9c047c Iustin Pop
    if isinstance(tags, set):
304 ff9c047c Iustin Pop
      bo["tags"] = list(tags)
305 ff9c047c Iustin Pop
    return bo
306 ff9c047c Iustin Pop
307 ff9c047c Iustin Pop
  @classmethod
308 ff9c047c Iustin Pop
  def FromDict(cls, val):
309 ff9c047c Iustin Pop
    """Custom function for instances.
310 ff9c047c Iustin Pop

311 ff9c047c Iustin Pop
    """
312 ff9c047c Iustin Pop
    obj = super(TaggableObject, cls).FromDict(val)
313 ff9c047c Iustin Pop
    if hasattr(obj, "tags") and isinstance(obj.tags, list):
314 ff9c047c Iustin Pop
      obj.tags = set(obj.tags)
315 ff9c047c Iustin Pop
    return obj
316 ff9c047c Iustin Pop
317 5c947f38 Iustin Pop
318 061af273 Andrea Spadaccini
class MasterNetworkParameters(ConfigObject):
319 061af273 Andrea Spadaccini
  """Network configuration parameters for the master
320 061af273 Andrea Spadaccini

321 061af273 Andrea Spadaccini
  @ivar name: master name
322 061af273 Andrea Spadaccini
  @ivar ip: master IP
323 061af273 Andrea Spadaccini
  @ivar netmask: master netmask
324 061af273 Andrea Spadaccini
  @ivar netdev: master network device
325 061af273 Andrea Spadaccini
  @ivar ip_family: master IP family
326 061af273 Andrea Spadaccini

327 061af273 Andrea Spadaccini
  """
328 061af273 Andrea Spadaccini
  __slots__ = [
329 061af273 Andrea Spadaccini
    "name",
330 061af273 Andrea Spadaccini
    "ip",
331 061af273 Andrea Spadaccini
    "netmask",
332 061af273 Andrea Spadaccini
    "netdev",
333 061af273 Andrea Spadaccini
    "ip_family"
334 061af273 Andrea Spadaccini
    ]
335 061af273 Andrea Spadaccini
336 061af273 Andrea Spadaccini
337 a8083063 Iustin Pop
class ConfigData(ConfigObject):
338 a8083063 Iustin Pop
  """Top-level config object."""
339 3df43542 Guido Trotter
  __slots__ = [
340 3df43542 Guido Trotter
    "version",
341 3df43542 Guido Trotter
    "cluster",
342 3df43542 Guido Trotter
    "nodes",
343 3df43542 Guido Trotter
    "nodegroups",
344 3df43542 Guido Trotter
    "instances",
345 3df43542 Guido Trotter
    "serial_no",
346 3df43542 Guido Trotter
    ] + _TIMESTAMPS
347 a8083063 Iustin Pop
348 ff9c047c Iustin Pop
  def ToDict(self):
349 ff9c047c Iustin Pop
    """Custom function for top-level config data.
350 ff9c047c Iustin Pop

351 ff9c047c Iustin Pop
    This just replaces the list of instances, nodes and the cluster
352 ff9c047c Iustin Pop
    with standard python types.
353 ff9c047c Iustin Pop

354 ff9c047c Iustin Pop
    """
355 ff9c047c Iustin Pop
    mydict = super(ConfigData, self).ToDict()
356 ff9c047c Iustin Pop
    mydict["cluster"] = mydict["cluster"].ToDict()
357 3df43542 Guido Trotter
    for key in "nodes", "instances", "nodegroups":
358 ff9c047c Iustin Pop
      mydict[key] = self._ContainerToDicts(mydict[key])
359 ff9c047c Iustin Pop
360 ff9c047c Iustin Pop
    return mydict
361 ff9c047c Iustin Pop
362 ff9c047c Iustin Pop
  @classmethod
363 ff9c047c Iustin Pop
  def FromDict(cls, val):
364 ff9c047c Iustin Pop
    """Custom function for top-level config data
365 ff9c047c Iustin Pop

366 ff9c047c Iustin Pop
    """
367 ff9c047c Iustin Pop
    obj = super(ConfigData, cls).FromDict(val)
368 ff9c047c Iustin Pop
    obj.cluster = Cluster.FromDict(obj.cluster)
369 ff9c047c Iustin Pop
    obj.nodes = cls._ContainerFromDicts(obj.nodes, dict, Node)
370 ff9c047c Iustin Pop
    obj.instances = cls._ContainerFromDicts(obj.instances, dict, Instance)
371 3df43542 Guido Trotter
    obj.nodegroups = cls._ContainerFromDicts(obj.nodegroups, dict, NodeGroup)
372 ff9c047c Iustin Pop
    return obj
373 ff9c047c Iustin Pop
374 51cb1581 Luca Bigliardi
  def HasAnyDiskOfType(self, dev_type):
375 51cb1581 Luca Bigliardi
    """Check if in there is at disk of the given type in the configuration.
376 51cb1581 Luca Bigliardi

377 51cb1581 Luca Bigliardi
    @type dev_type: L{constants.LDS_BLOCK}
378 51cb1581 Luca Bigliardi
    @param dev_type: the type to look for
379 51cb1581 Luca Bigliardi
    @rtype: boolean
380 51cb1581 Luca Bigliardi
    @return: boolean indicating if a disk of the given type was found or not
381 51cb1581 Luca Bigliardi

382 51cb1581 Luca Bigliardi
    """
383 51cb1581 Luca Bigliardi
    for instance in self.instances.values():
384 51cb1581 Luca Bigliardi
      for disk in instance.disks:
385 51cb1581 Luca Bigliardi
        if disk.IsBasedOnDiskType(dev_type):
386 51cb1581 Luca Bigliardi
          return True
387 51cb1581 Luca Bigliardi
    return False
388 51cb1581 Luca Bigliardi
389 90d726a8 Iustin Pop
  def UpgradeConfig(self):
390 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
391 90d726a8 Iustin Pop

392 90d726a8 Iustin Pop
    """
393 90d726a8 Iustin Pop
    self.cluster.UpgradeConfig()
394 90d726a8 Iustin Pop
    for node in self.nodes.values():
395 90d726a8 Iustin Pop
      node.UpgradeConfig()
396 90d726a8 Iustin Pop
    for instance in self.instances.values():
397 90d726a8 Iustin Pop
      instance.UpgradeConfig()
398 3df43542 Guido Trotter
    if self.nodegroups is None:
399 3df43542 Guido Trotter
      self.nodegroups = {}
400 3df43542 Guido Trotter
    for nodegroup in self.nodegroups.values():
401 3df43542 Guido Trotter
      nodegroup.UpgradeConfig()
402 ee2f0ed4 Luca Bigliardi
    if self.cluster.drbd_usermode_helper is None:
403 ee2f0ed4 Luca Bigliardi
      # To decide if we set an helper let's check if at least one instance has
404 ee2f0ed4 Luca Bigliardi
      # a DRBD disk. This does not cover all the possible scenarios but it
405 ee2f0ed4 Luca Bigliardi
      # gives a good approximation.
406 ee2f0ed4 Luca Bigliardi
      if self.HasAnyDiskOfType(constants.LD_DRBD8):
407 ee2f0ed4 Luca Bigliardi
        self.cluster.drbd_usermode_helper = constants.DEFAULT_DRBD_HELPER
408 90d726a8 Iustin Pop
409 a8083063 Iustin Pop
410 a8083063 Iustin Pop
class NIC(ConfigObject):
411 a8083063 Iustin Pop
  """Config object representing a network card."""
412 1177d70e Guido Trotter
  __slots__ = ["mac", "ip", "nicparams"]
413 a8083063 Iustin Pop
414 255e19d4 Guido Trotter
  @classmethod
415 255e19d4 Guido Trotter
  def CheckParameterSyntax(cls, nicparams):
416 255e19d4 Guido Trotter
    """Check the given parameters for validity.
417 255e19d4 Guido Trotter

418 255e19d4 Guido Trotter
    @type nicparams:  dict
419 255e19d4 Guido Trotter
    @param nicparams: dictionary with parameter names/value
420 255e19d4 Guido Trotter
    @raise errors.ConfigurationError: when a parameter is not valid
421 255e19d4 Guido Trotter

422 255e19d4 Guido Trotter
    """
423 e8448672 Agata Murawska
    if (nicparams[constants.NIC_MODE] not in constants.NIC_VALID_MODES and
424 e8448672 Agata Murawska
        nicparams[constants.NIC_MODE] != constants.VALUE_AUTO):
425 255e19d4 Guido Trotter
      err = "Invalid nic mode: %s" % nicparams[constants.NIC_MODE]
426 255e19d4 Guido Trotter
      raise errors.ConfigurationError(err)
427 255e19d4 Guido Trotter
428 0c9d32c1 Guido Trotter
    if (nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED and
429 255e19d4 Guido Trotter
        not nicparams[constants.NIC_LINK]):
430 255e19d4 Guido Trotter
      err = "Missing bridged nic link"
431 255e19d4 Guido Trotter
      raise errors.ConfigurationError(err)
432 255e19d4 Guido Trotter
433 a8083063 Iustin Pop
434 a8083063 Iustin Pop
class Disk(ConfigObject):
435 a8083063 Iustin Pop
  """Config object representing a block device."""
436 a8083063 Iustin Pop
  __slots__ = ["dev_type", "logical_id", "physical_id",
437 08db7c5c Iustin Pop
               "children", "iv_name", "size", "mode"]
438 a8083063 Iustin Pop
439 a8083063 Iustin Pop
  def CreateOnSecondary(self):
440 a8083063 Iustin Pop
    """Test if this device needs to be created on a secondary node."""
441 00fb8246 Michael Hanselmann
    return self.dev_type in (constants.LD_DRBD8, constants.LD_LV)
442 a8083063 Iustin Pop
443 a8083063 Iustin Pop
  def AssembleOnSecondary(self):
444 a8083063 Iustin Pop
    """Test if this device needs to be assembled on a secondary node."""
445 00fb8246 Michael Hanselmann
    return self.dev_type in (constants.LD_DRBD8, constants.LD_LV)
446 a8083063 Iustin Pop
447 a8083063 Iustin Pop
  def OpenOnSecondary(self):
448 a8083063 Iustin Pop
    """Test if this device needs to be opened on a secondary node."""
449 fe96220b Iustin Pop
    return self.dev_type in (constants.LD_LV,)
450 a8083063 Iustin Pop
451 222f2dd5 Iustin Pop
  def StaticDevPath(self):
452 222f2dd5 Iustin Pop
    """Return the device path if this device type has a static one.
453 222f2dd5 Iustin Pop

454 222f2dd5 Iustin Pop
    Some devices (LVM for example) live always at the same /dev/ path,
455 222f2dd5 Iustin Pop
    irrespective of their status. For such devices, we return this
456 222f2dd5 Iustin Pop
    path, for others we return None.
457 222f2dd5 Iustin Pop

458 e51db2a6 Iustin Pop
    @warning: The path returned is not a normalized pathname; callers
459 e51db2a6 Iustin Pop
        should check that it is a valid path.
460 e51db2a6 Iustin Pop

461 222f2dd5 Iustin Pop
    """
462 222f2dd5 Iustin Pop
    if self.dev_type == constants.LD_LV:
463 222f2dd5 Iustin Pop
      return "/dev/%s/%s" % (self.logical_id[0], self.logical_id[1])
464 b6135bbc Apollon Oikonomopoulos
    elif self.dev_type == constants.LD_BLOCKDEV:
465 b6135bbc Apollon Oikonomopoulos
      return self.logical_id[1]
466 222f2dd5 Iustin Pop
    return None
467 222f2dd5 Iustin Pop
468 fc1dc9d7 Iustin Pop
  def ChildrenNeeded(self):
469 fc1dc9d7 Iustin Pop
    """Compute the needed number of children for activation.
470 fc1dc9d7 Iustin Pop

471 fc1dc9d7 Iustin Pop
    This method will return either -1 (all children) or a positive
472 fc1dc9d7 Iustin Pop
    number denoting the minimum number of children needed for
473 fc1dc9d7 Iustin Pop
    activation (only mirrored devices will usually return >=0).
474 fc1dc9d7 Iustin Pop

475 fc1dc9d7 Iustin Pop
    Currently, only DRBD8 supports diskless activation (therefore we
476 fc1dc9d7 Iustin Pop
    return 0), for all other we keep the previous semantics and return
477 fc1dc9d7 Iustin Pop
    -1.
478 fc1dc9d7 Iustin Pop

479 fc1dc9d7 Iustin Pop
    """
480 fc1dc9d7 Iustin Pop
    if self.dev_type == constants.LD_DRBD8:
481 fc1dc9d7 Iustin Pop
      return 0
482 fc1dc9d7 Iustin Pop
    return -1
483 fc1dc9d7 Iustin Pop
484 51cb1581 Luca Bigliardi
  def IsBasedOnDiskType(self, dev_type):
485 51cb1581 Luca Bigliardi
    """Check if the disk or its children are based on the given type.
486 51cb1581 Luca Bigliardi

487 51cb1581 Luca Bigliardi
    @type dev_type: L{constants.LDS_BLOCK}
488 51cb1581 Luca Bigliardi
    @param dev_type: the type to look for
489 51cb1581 Luca Bigliardi
    @rtype: boolean
490 51cb1581 Luca Bigliardi
    @return: boolean indicating if a device of the given type was found or not
491 51cb1581 Luca Bigliardi

492 51cb1581 Luca Bigliardi
    """
493 51cb1581 Luca Bigliardi
    if self.children:
494 51cb1581 Luca Bigliardi
      for child in self.children:
495 51cb1581 Luca Bigliardi
        if child.IsBasedOnDiskType(dev_type):
496 51cb1581 Luca Bigliardi
          return True
497 51cb1581 Luca Bigliardi
    return self.dev_type == dev_type
498 51cb1581 Luca Bigliardi
499 a8083063 Iustin Pop
  def GetNodes(self, node):
500 a8083063 Iustin Pop
    """This function returns the nodes this device lives on.
501 a8083063 Iustin Pop

502 a8083063 Iustin Pop
    Given the node on which the parent of the device lives on (or, in
503 a8083063 Iustin Pop
    case of a top-level device, the primary node of the devices'
504 a8083063 Iustin Pop
    instance), this function will return a list of nodes on which this
505 a8083063 Iustin Pop
    devices needs to (or can) be assembled.
506 a8083063 Iustin Pop

507 a8083063 Iustin Pop
    """
508 b6135bbc Apollon Oikonomopoulos
    if self.dev_type in [constants.LD_LV, constants.LD_FILE,
509 b6135bbc Apollon Oikonomopoulos
                         constants.LD_BLOCKDEV]:
510 a8083063 Iustin Pop
      result = [node]
511 a1f445d3 Iustin Pop
    elif self.dev_type in constants.LDS_DRBD:
512 a8083063 Iustin Pop
      result = [self.logical_id[0], self.logical_id[1]]
513 a8083063 Iustin Pop
      if node not in result:
514 3ecf6786 Iustin Pop
        raise errors.ConfigurationError("DRBD device passed unknown node")
515 a8083063 Iustin Pop
    else:
516 3ecf6786 Iustin Pop
      raise errors.ProgrammerError("Unhandled device type %s" % self.dev_type)
517 a8083063 Iustin Pop
    return result
518 a8083063 Iustin Pop
519 a8083063 Iustin Pop
  def ComputeNodeTree(self, parent_node):
520 a8083063 Iustin Pop
    """Compute the node/disk tree for this disk and its children.
521 a8083063 Iustin Pop

522 a8083063 Iustin Pop
    This method, given the node on which the parent disk lives, will
523 a8083063 Iustin Pop
    return the list of all (node, disk) pairs which describe the disk
524 abdf0113 Iustin Pop
    tree in the most compact way. For example, a drbd/lvm stack
525 abdf0113 Iustin Pop
    will be returned as (primary_node, drbd) and (secondary_node, drbd)
526 abdf0113 Iustin Pop
    which represents all the top-level devices on the nodes.
527 a8083063 Iustin Pop

528 a8083063 Iustin Pop
    """
529 a8083063 Iustin Pop
    my_nodes = self.GetNodes(parent_node)
530 a8083063 Iustin Pop
    result = [(node, self) for node in my_nodes]
531 a8083063 Iustin Pop
    if not self.children:
532 a8083063 Iustin Pop
      # leaf device
533 a8083063 Iustin Pop
      return result
534 a8083063 Iustin Pop
    for node in my_nodes:
535 a8083063 Iustin Pop
      for child in self.children:
536 a8083063 Iustin Pop
        child_result = child.ComputeNodeTree(node)
537 a8083063 Iustin Pop
        if len(child_result) == 1:
538 a8083063 Iustin Pop
          # child (and all its descendants) is simple, doesn't split
539 a8083063 Iustin Pop
          # over multiple hosts, so we don't need to describe it, our
540 a8083063 Iustin Pop
          # own entry for this node describes it completely
541 a8083063 Iustin Pop
          continue
542 a8083063 Iustin Pop
        else:
543 a8083063 Iustin Pop
          # check if child nodes differ from my nodes; note that
544 a8083063 Iustin Pop
          # subdisk can differ from the child itself, and be instead
545 a8083063 Iustin Pop
          # one of its descendants
546 a8083063 Iustin Pop
          for subnode, subdisk in child_result:
547 a8083063 Iustin Pop
            if subnode not in my_nodes:
548 a8083063 Iustin Pop
              result.append((subnode, subdisk))
549 a8083063 Iustin Pop
            # otherwise child is under our own node, so we ignore this
550 a8083063 Iustin Pop
            # entry (but probably the other results in the list will
551 a8083063 Iustin Pop
            # be different)
552 a8083063 Iustin Pop
    return result
553 a8083063 Iustin Pop
554 6d33a6eb Iustin Pop
  def ComputeGrowth(self, amount):
555 6d33a6eb Iustin Pop
    """Compute the per-VG growth requirements.
556 6d33a6eb Iustin Pop

557 6d33a6eb Iustin Pop
    This only works for VG-based disks.
558 6d33a6eb Iustin Pop

559 6d33a6eb Iustin Pop
    @type amount: integer
560 6d33a6eb Iustin Pop
    @param amount: the desired increase in (user-visible) disk space
561 6d33a6eb Iustin Pop
    @rtype: dict
562 6d33a6eb Iustin Pop
    @return: a dictionary of volume-groups and the required size
563 6d33a6eb Iustin Pop

564 6d33a6eb Iustin Pop
    """
565 6d33a6eb Iustin Pop
    if self.dev_type == constants.LD_LV:
566 6d33a6eb Iustin Pop
      return {self.logical_id[0]: amount}
567 6d33a6eb Iustin Pop
    elif self.dev_type == constants.LD_DRBD8:
568 6d33a6eb Iustin Pop
      if self.children:
569 6d33a6eb Iustin Pop
        return self.children[0].ComputeGrowth(amount)
570 6d33a6eb Iustin Pop
      else:
571 6d33a6eb Iustin Pop
        return {}
572 6d33a6eb Iustin Pop
    else:
573 6d33a6eb Iustin Pop
      # Other disk types do not require VG space
574 6d33a6eb Iustin Pop
      return {}
575 6d33a6eb Iustin Pop
576 acec9d51 Iustin Pop
  def RecordGrow(self, amount):
577 acec9d51 Iustin Pop
    """Update the size of this disk after growth.
578 acec9d51 Iustin Pop

579 acec9d51 Iustin Pop
    This method recurses over the disks's children and updates their
580 acec9d51 Iustin Pop
    size correspondigly. The method needs to be kept in sync with the
581 acec9d51 Iustin Pop
    actual algorithms from bdev.
582 acec9d51 Iustin Pop

583 acec9d51 Iustin Pop
    """
584 4b97f902 Apollon Oikonomopoulos
    if self.dev_type in (constants.LD_LV, constants.LD_FILE):
585 acec9d51 Iustin Pop
      self.size += amount
586 acec9d51 Iustin Pop
    elif self.dev_type == constants.LD_DRBD8:
587 acec9d51 Iustin Pop
      if self.children:
588 acec9d51 Iustin Pop
        self.children[0].RecordGrow(amount)
589 acec9d51 Iustin Pop
      self.size += amount
590 acec9d51 Iustin Pop
    else:
591 acec9d51 Iustin Pop
      raise errors.ProgrammerError("Disk.RecordGrow called for unsupported"
592 acec9d51 Iustin Pop
                                   " disk type %s" % self.dev_type)
593 acec9d51 Iustin Pop
594 a805ec18 Iustin Pop
  def UnsetSize(self):
595 a805ec18 Iustin Pop
    """Sets recursively the size to zero for the disk and its children.
596 a805ec18 Iustin Pop

597 a805ec18 Iustin Pop
    """
598 a805ec18 Iustin Pop
    if self.children:
599 a805ec18 Iustin Pop
      for child in self.children:
600 a805ec18 Iustin Pop
        child.UnsetSize()
601 a805ec18 Iustin Pop
    self.size = 0
602 a805ec18 Iustin Pop
603 0402302c Iustin Pop
  def SetPhysicalID(self, target_node, nodes_ip):
604 0402302c Iustin Pop
    """Convert the logical ID to the physical ID.
605 0402302c Iustin Pop

606 0402302c Iustin Pop
    This is used only for drbd, which needs ip/port configuration.
607 0402302c Iustin Pop

608 0402302c Iustin Pop
    The routine descends down and updates its children also, because
609 0402302c Iustin Pop
    this helps when the only the top device is passed to the remote
610 0402302c Iustin Pop
    node.
611 0402302c Iustin Pop

612 0402302c Iustin Pop
    Arguments:
613 0402302c Iustin Pop
      - target_node: the node we wish to configure for
614 0402302c Iustin Pop
      - nodes_ip: a mapping of node name to ip
615 0402302c Iustin Pop

616 0402302c Iustin Pop
    The target_node must exist in in nodes_ip, and must be one of the
617 0402302c Iustin Pop
    nodes in the logical ID for each of the DRBD devices encountered
618 0402302c Iustin Pop
    in the disk tree.
619 0402302c Iustin Pop

620 0402302c Iustin Pop
    """
621 0402302c Iustin Pop
    if self.children:
622 0402302c Iustin Pop
      for child in self.children:
623 0402302c Iustin Pop
        child.SetPhysicalID(target_node, nodes_ip)
624 0402302c Iustin Pop
625 0402302c Iustin Pop
    if self.logical_id is None and self.physical_id is not None:
626 0402302c Iustin Pop
      return
627 0402302c Iustin Pop
    if self.dev_type in constants.LDS_DRBD:
628 f9518d38 Iustin Pop
      pnode, snode, port, pminor, sminor, secret = self.logical_id
629 0402302c Iustin Pop
      if target_node not in (pnode, snode):
630 0402302c Iustin Pop
        raise errors.ConfigurationError("DRBD device not knowing node %s" %
631 0402302c Iustin Pop
                                        target_node)
632 0402302c Iustin Pop
      pnode_ip = nodes_ip.get(pnode, None)
633 0402302c Iustin Pop
      snode_ip = nodes_ip.get(snode, None)
634 0402302c Iustin Pop
      if pnode_ip is None or snode_ip is None:
635 0402302c Iustin Pop
        raise errors.ConfigurationError("Can't find primary or secondary node"
636 0402302c Iustin Pop
                                        " for %s" % str(self))
637 ffa1c0dc Iustin Pop
      p_data = (pnode_ip, port)
638 ffa1c0dc Iustin Pop
      s_data = (snode_ip, port)
639 0402302c Iustin Pop
      if pnode == target_node:
640 f9518d38 Iustin Pop
        self.physical_id = p_data + s_data + (pminor, secret)
641 0402302c Iustin Pop
      else: # it must be secondary, we tested above
642 f9518d38 Iustin Pop
        self.physical_id = s_data + p_data + (sminor, secret)
643 0402302c Iustin Pop
    else:
644 0402302c Iustin Pop
      self.physical_id = self.logical_id
645 0402302c Iustin Pop
    return
646 0402302c Iustin Pop
647 ff9c047c Iustin Pop
  def ToDict(self):
648 ff9c047c Iustin Pop
    """Disk-specific conversion to standard python types.
649 ff9c047c Iustin Pop

650 ff9c047c Iustin Pop
    This replaces the children lists of objects with lists of
651 ff9c047c Iustin Pop
    standard python types.
652 ff9c047c Iustin Pop

653 ff9c047c Iustin Pop
    """
654 ff9c047c Iustin Pop
    bo = super(Disk, self).ToDict()
655 ff9c047c Iustin Pop
656 ff9c047c Iustin Pop
    for attr in ("children",):
657 ff9c047c Iustin Pop
      alist = bo.get(attr, None)
658 ff9c047c Iustin Pop
      if alist:
659 ff9c047c Iustin Pop
        bo[attr] = self._ContainerToDicts(alist)
660 ff9c047c Iustin Pop
    return bo
661 ff9c047c Iustin Pop
662 ff9c047c Iustin Pop
  @classmethod
663 ff9c047c Iustin Pop
  def FromDict(cls, val):
664 ff9c047c Iustin Pop
    """Custom function for Disks
665 ff9c047c Iustin Pop

666 ff9c047c Iustin Pop
    """
667 ff9c047c Iustin Pop
    obj = super(Disk, cls).FromDict(val)
668 ff9c047c Iustin Pop
    if obj.children:
669 ff9c047c Iustin Pop
      obj.children = cls._ContainerFromDicts(obj.children, list, Disk)
670 ff9c047c Iustin Pop
    if obj.logical_id and isinstance(obj.logical_id, list):
671 ff9c047c Iustin Pop
      obj.logical_id = tuple(obj.logical_id)
672 ff9c047c Iustin Pop
    if obj.physical_id and isinstance(obj.physical_id, list):
673 ff9c047c Iustin Pop
      obj.physical_id = tuple(obj.physical_id)
674 f9518d38 Iustin Pop
    if obj.dev_type in constants.LDS_DRBD:
675 f9518d38 Iustin Pop
      # we need a tuple of length six here
676 f9518d38 Iustin Pop
      if len(obj.logical_id) < 6:
677 f9518d38 Iustin Pop
        obj.logical_id += (None,) * (6 - len(obj.logical_id))
678 ff9c047c Iustin Pop
    return obj
679 ff9c047c Iustin Pop
680 65a15336 Iustin Pop
  def __str__(self):
681 65a15336 Iustin Pop
    """Custom str() formatter for disks.
682 65a15336 Iustin Pop

683 65a15336 Iustin Pop
    """
684 65a15336 Iustin Pop
    if self.dev_type == constants.LD_LV:
685 e687ec01 Michael Hanselmann
      val = "<LogicalVolume(/dev/%s/%s" % self.logical_id
686 65a15336 Iustin Pop
    elif self.dev_type in constants.LDS_DRBD:
687 89f28b76 Iustin Pop
      node_a, node_b, port, minor_a, minor_b = self.logical_id[:5]
688 00fb8246 Michael Hanselmann
      val = "<DRBD8("
689 073ca59e Iustin Pop
      if self.physical_id is None:
690 073ca59e Iustin Pop
        phy = "unconfigured"
691 073ca59e Iustin Pop
      else:
692 073ca59e Iustin Pop
        phy = ("configured as %s:%s %s:%s" %
693 25a915d0 Iustin Pop
               (self.physical_id[0], self.physical_id[1],
694 25a915d0 Iustin Pop
                self.physical_id[2], self.physical_id[3]))
695 073ca59e Iustin Pop
696 89f28b76 Iustin Pop
      val += ("hosts=%s/%d-%s/%d, port=%s, %s, " %
697 89f28b76 Iustin Pop
              (node_a, minor_a, node_b, minor_b, port, phy))
698 65a15336 Iustin Pop
      if self.children and self.children.count(None) == 0:
699 65a15336 Iustin Pop
        val += "backend=%s, metadev=%s" % (self.children[0], self.children[1])
700 65a15336 Iustin Pop
      else:
701 65a15336 Iustin Pop
        val += "no local storage"
702 65a15336 Iustin Pop
    else:
703 65a15336 Iustin Pop
      val = ("<Disk(type=%s, logical_id=%s, physical_id=%s, children=%s" %
704 65a15336 Iustin Pop
             (self.dev_type, self.logical_id, self.physical_id, self.children))
705 65a15336 Iustin Pop
    if self.iv_name is None:
706 65a15336 Iustin Pop
      val += ", not visible"
707 65a15336 Iustin Pop
    else:
708 65a15336 Iustin Pop
      val += ", visible as /dev/%s" % self.iv_name
709 fd965830 Iustin Pop
    if isinstance(self.size, int):
710 fd965830 Iustin Pop
      val += ", size=%dm)>" % self.size
711 fd965830 Iustin Pop
    else:
712 fd965830 Iustin Pop
      val += ", size='%s')>" % (self.size,)
713 65a15336 Iustin Pop
    return val
714 65a15336 Iustin Pop
715 332d0e37 Iustin Pop
  def Verify(self):
716 332d0e37 Iustin Pop
    """Checks that this disk is correctly configured.
717 332d0e37 Iustin Pop

718 332d0e37 Iustin Pop
    """
719 7c4d6c7b Michael Hanselmann
    all_errors = []
720 332d0e37 Iustin Pop
    if self.mode not in constants.DISK_ACCESS_SET:
721 7c4d6c7b Michael Hanselmann
      all_errors.append("Disk access mode '%s' is invalid" % (self.mode, ))
722 7c4d6c7b Michael Hanselmann
    return all_errors
723 332d0e37 Iustin Pop
724 90d726a8 Iustin Pop
  def UpgradeConfig(self):
725 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
726 90d726a8 Iustin Pop

727 90d726a8 Iustin Pop
    """
728 90d726a8 Iustin Pop
    if self.children:
729 90d726a8 Iustin Pop
      for child in self.children:
730 90d726a8 Iustin Pop
        child.UpgradeConfig()
731 90d726a8 Iustin Pop
    # add here config upgrade for this disk
732 90d726a8 Iustin Pop
733 a8083063 Iustin Pop
734 ec29fe40 Iustin Pop
class Instance(TaggableObject):
735 a8083063 Iustin Pop
  """Config object representing an instance."""
736 154b9580 Balazs Lecz
  __slots__ = [
737 a8083063 Iustin Pop
    "name",
738 a8083063 Iustin Pop
    "primary_node",
739 a8083063 Iustin Pop
    "os",
740 e69d05fd Iustin Pop
    "hypervisor",
741 5bf7b5cf Iustin Pop
    "hvparams",
742 5bf7b5cf Iustin Pop
    "beparams",
743 1bdcbbab Iustin Pop
    "osparams",
744 0d68c45d Iustin Pop
    "admin_up",
745 a8083063 Iustin Pop
    "nics",
746 a8083063 Iustin Pop
    "disks",
747 a8083063 Iustin Pop
    "disk_template",
748 58acb49d Alexander Schreiber
    "network_port",
749 be1fa613 Iustin Pop
    "serial_no",
750 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
751 a8083063 Iustin Pop
752 a8083063 Iustin Pop
  def _ComputeSecondaryNodes(self):
753 a8083063 Iustin Pop
    """Compute the list of secondary nodes.
754 a8083063 Iustin Pop

755 cfcc5c6d Iustin Pop
    This is a simple wrapper over _ComputeAllNodes.
756 cfcc5c6d Iustin Pop

757 cfcc5c6d Iustin Pop
    """
758 cfcc5c6d Iustin Pop
    all_nodes = set(self._ComputeAllNodes())
759 cfcc5c6d Iustin Pop
    all_nodes.discard(self.primary_node)
760 cfcc5c6d Iustin Pop
    return tuple(all_nodes)
761 cfcc5c6d Iustin Pop
762 cfcc5c6d Iustin Pop
  secondary_nodes = property(_ComputeSecondaryNodes, None, None,
763 cfcc5c6d Iustin Pop
                             "List of secondary nodes")
764 cfcc5c6d Iustin Pop
765 cfcc5c6d Iustin Pop
  def _ComputeAllNodes(self):
766 cfcc5c6d Iustin Pop
    """Compute the list of all nodes.
767 cfcc5c6d Iustin Pop

768 a8083063 Iustin Pop
    Since the data is already there (in the drbd disks), keeping it as
769 a8083063 Iustin Pop
    a separate normal attribute is redundant and if not properly
770 a8083063 Iustin Pop
    synchronised can cause problems. Thus it's better to compute it
771 a8083063 Iustin Pop
    dynamically.
772 a8083063 Iustin Pop

773 a8083063 Iustin Pop
    """
774 cfcc5c6d Iustin Pop
    def _Helper(nodes, device):
775 cfcc5c6d Iustin Pop
      """Recursively computes nodes given a top device."""
776 a1f445d3 Iustin Pop
      if device.dev_type in constants.LDS_DRBD:
777 cfcc5c6d Iustin Pop
        nodea, nodeb = device.logical_id[:2]
778 cfcc5c6d Iustin Pop
        nodes.add(nodea)
779 cfcc5c6d Iustin Pop
        nodes.add(nodeb)
780 a8083063 Iustin Pop
      if device.children:
781 a8083063 Iustin Pop
        for child in device.children:
782 cfcc5c6d Iustin Pop
          _Helper(nodes, child)
783 a8083063 Iustin Pop
784 cfcc5c6d Iustin Pop
    all_nodes = set()
785 99c7b2a1 Iustin Pop
    all_nodes.add(self.primary_node)
786 a8083063 Iustin Pop
    for device in self.disks:
787 cfcc5c6d Iustin Pop
      _Helper(all_nodes, device)
788 cfcc5c6d Iustin Pop
    return tuple(all_nodes)
789 a8083063 Iustin Pop
790 cfcc5c6d Iustin Pop
  all_nodes = property(_ComputeAllNodes, None, None,
791 cfcc5c6d Iustin Pop
                       "List of all nodes of the instance")
792 a8083063 Iustin Pop
793 a8083063 Iustin Pop
  def MapLVsByNode(self, lvmap=None, devs=None, node=None):
794 a8083063 Iustin Pop
    """Provide a mapping of nodes to LVs this instance owns.
795 a8083063 Iustin Pop

796 c41eea6e Iustin Pop
    This function figures out what logical volumes should belong on
797 c41eea6e Iustin Pop
    which nodes, recursing through a device tree.
798 a8083063 Iustin Pop

799 c41eea6e Iustin Pop
    @param lvmap: optional dictionary to receive the
800 c41eea6e Iustin Pop
        'node' : ['lv', ...] data.
801 a8083063 Iustin Pop

802 84d7e26b Dmitry Chernyak
    @return: None if lvmap arg is given, otherwise, a dictionary of
803 84d7e26b Dmitry Chernyak
        the form { 'nodename' : ['volume1', 'volume2', ...], ... };
804 84d7e26b Dmitry Chernyak
        volumeN is of the form "vg_name/lv_name", compatible with
805 84d7e26b Dmitry Chernyak
        GetVolumeList()
806 a8083063 Iustin Pop

807 a8083063 Iustin Pop
    """
808 a8083063 Iustin Pop
    if node == None:
809 a8083063 Iustin Pop
      node = self.primary_node
810 a8083063 Iustin Pop
811 a8083063 Iustin Pop
    if lvmap is None:
812 e687ec01 Michael Hanselmann
      lvmap = {
813 e687ec01 Michael Hanselmann
        node: [],
814 e687ec01 Michael Hanselmann
        }
815 a8083063 Iustin Pop
      ret = lvmap
816 a8083063 Iustin Pop
    else:
817 a8083063 Iustin Pop
      if not node in lvmap:
818 a8083063 Iustin Pop
        lvmap[node] = []
819 a8083063 Iustin Pop
      ret = None
820 a8083063 Iustin Pop
821 a8083063 Iustin Pop
    if not devs:
822 a8083063 Iustin Pop
      devs = self.disks
823 a8083063 Iustin Pop
824 a8083063 Iustin Pop
    for dev in devs:
825 fe96220b Iustin Pop
      if dev.dev_type == constants.LD_LV:
826 e687ec01 Michael Hanselmann
        lvmap[node].append(dev.logical_id[0] + "/" + dev.logical_id[1])
827 a8083063 Iustin Pop
828 a1f445d3 Iustin Pop
      elif dev.dev_type in constants.LDS_DRBD:
829 a8083063 Iustin Pop
        if dev.children:
830 a8083063 Iustin Pop
          self.MapLVsByNode(lvmap, dev.children, dev.logical_id[0])
831 a8083063 Iustin Pop
          self.MapLVsByNode(lvmap, dev.children, dev.logical_id[1])
832 a8083063 Iustin Pop
833 a8083063 Iustin Pop
      elif dev.children:
834 a8083063 Iustin Pop
        self.MapLVsByNode(lvmap, dev.children, node)
835 a8083063 Iustin Pop
836 a8083063 Iustin Pop
    return ret
837 a8083063 Iustin Pop
838 ad24e046 Iustin Pop
  def FindDisk(self, idx):
839 ad24e046 Iustin Pop
    """Find a disk given having a specified index.
840 644eeef9 Iustin Pop

841 ad24e046 Iustin Pop
    This is just a wrapper that does validation of the index.
842 644eeef9 Iustin Pop

843 ad24e046 Iustin Pop
    @type idx: int
844 ad24e046 Iustin Pop
    @param idx: the disk index
845 ad24e046 Iustin Pop
    @rtype: L{Disk}
846 ad24e046 Iustin Pop
    @return: the corresponding disk
847 ad24e046 Iustin Pop
    @raise errors.OpPrereqError: when the given index is not valid
848 644eeef9 Iustin Pop

849 ad24e046 Iustin Pop
    """
850 ad24e046 Iustin Pop
    try:
851 ad24e046 Iustin Pop
      idx = int(idx)
852 ad24e046 Iustin Pop
      return self.disks[idx]
853 691744c4 Iustin Pop
    except (TypeError, ValueError), err:
854 debac808 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index: '%s'" % str(err),
855 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
856 ad24e046 Iustin Pop
    except IndexError:
857 ad24e046 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index: %d (instace has disks"
858 daa55b04 Michael Hanselmann
                                 " 0 to %d" % (idx, len(self.disks) - 1),
859 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
860 644eeef9 Iustin Pop
861 ff9c047c Iustin Pop
  def ToDict(self):
862 ff9c047c Iustin Pop
    """Instance-specific conversion to standard python types.
863 ff9c047c Iustin Pop

864 ff9c047c Iustin Pop
    This replaces the children lists of objects with lists of standard
865 ff9c047c Iustin Pop
    python types.
866 ff9c047c Iustin Pop

867 ff9c047c Iustin Pop
    """
868 ff9c047c Iustin Pop
    bo = super(Instance, self).ToDict()
869 ff9c047c Iustin Pop
870 ff9c047c Iustin Pop
    for attr in "nics", "disks":
871 ff9c047c Iustin Pop
      alist = bo.get(attr, None)
872 ff9c047c Iustin Pop
      if alist:
873 ff9c047c Iustin Pop
        nlist = self._ContainerToDicts(alist)
874 ff9c047c Iustin Pop
      else:
875 ff9c047c Iustin Pop
        nlist = []
876 ff9c047c Iustin Pop
      bo[attr] = nlist
877 ff9c047c Iustin Pop
    return bo
878 ff9c047c Iustin Pop
879 ff9c047c Iustin Pop
  @classmethod
880 ff9c047c Iustin Pop
  def FromDict(cls, val):
881 ff9c047c Iustin Pop
    """Custom function for instances.
882 ff9c047c Iustin Pop

883 ff9c047c Iustin Pop
    """
884 ff9c047c Iustin Pop
    obj = super(Instance, cls).FromDict(val)
885 ff9c047c Iustin Pop
    obj.nics = cls._ContainerFromDicts(obj.nics, list, NIC)
886 ff9c047c Iustin Pop
    obj.disks = cls._ContainerFromDicts(obj.disks, list, Disk)
887 ff9c047c Iustin Pop
    return obj
888 ff9c047c Iustin Pop
889 90d726a8 Iustin Pop
  def UpgradeConfig(self):
890 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
891 90d726a8 Iustin Pop

892 90d726a8 Iustin Pop
    """
893 90d726a8 Iustin Pop
    for nic in self.nics:
894 90d726a8 Iustin Pop
      nic.UpgradeConfig()
895 90d726a8 Iustin Pop
    for disk in self.disks:
896 90d726a8 Iustin Pop
      disk.UpgradeConfig()
897 7736a5f2 Iustin Pop
    if self.hvparams:
898 7736a5f2 Iustin Pop
      for key in constants.HVC_GLOBALS:
899 7736a5f2 Iustin Pop
        try:
900 7736a5f2 Iustin Pop
          del self.hvparams[key]
901 7736a5f2 Iustin Pop
        except KeyError:
902 7736a5f2 Iustin Pop
          pass
903 1bdcbbab Iustin Pop
    if self.osparams is None:
904 1bdcbbab Iustin Pop
      self.osparams = {}
905 90d726a8 Iustin Pop
906 a8083063 Iustin Pop
907 a8083063 Iustin Pop
class OS(ConfigObject):
908 b41b3516 Iustin Pop
  """Config object representing an operating system.
909 b41b3516 Iustin Pop

910 b41b3516 Iustin Pop
  @type supported_parameters: list
911 b41b3516 Iustin Pop
  @ivar supported_parameters: a list of tuples, name and description,
912 b41b3516 Iustin Pop
      containing the supported parameters by this OS
913 b41b3516 Iustin Pop

914 870dc44c Iustin Pop
  @type VARIANT_DELIM: string
915 870dc44c Iustin Pop
  @cvar VARIANT_DELIM: the variant delimiter
916 870dc44c Iustin Pop

917 b41b3516 Iustin Pop
  """
918 a8083063 Iustin Pop
  __slots__ = [
919 a8083063 Iustin Pop
    "name",
920 a8083063 Iustin Pop
    "path",
921 082a7f91 Guido Trotter
    "api_versions",
922 a8083063 Iustin Pop
    "create_script",
923 a8083063 Iustin Pop
    "export_script",
924 386b57af Iustin Pop
    "import_script",
925 386b57af Iustin Pop
    "rename_script",
926 b41b3516 Iustin Pop
    "verify_script",
927 6d79896b Guido Trotter
    "supported_variants",
928 b41b3516 Iustin Pop
    "supported_parameters",
929 a8083063 Iustin Pop
    ]
930 a8083063 Iustin Pop
931 870dc44c Iustin Pop
  VARIANT_DELIM = "+"
932 870dc44c Iustin Pop
933 870dc44c Iustin Pop
  @classmethod
934 870dc44c Iustin Pop
  def SplitNameVariant(cls, name):
935 870dc44c Iustin Pop
    """Splits the name into the proper name and variant.
936 870dc44c Iustin Pop

937 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
938 870dc44c Iustin Pop
    @rtype: list
939 870dc44c Iustin Pop
    @return: a list of two elements; if the original name didn't
940 870dc44c Iustin Pop
        contain a variant, it's returned as an empty string
941 870dc44c Iustin Pop

942 870dc44c Iustin Pop
    """
943 870dc44c Iustin Pop
    nv = name.split(cls.VARIANT_DELIM, 1)
944 870dc44c Iustin Pop
    if len(nv) == 1:
945 870dc44c Iustin Pop
      nv.append("")
946 870dc44c Iustin Pop
    return nv
947 870dc44c Iustin Pop
948 870dc44c Iustin Pop
  @classmethod
949 870dc44c Iustin Pop
  def GetName(cls, name):
950 870dc44c Iustin Pop
    """Returns the proper name of the os (without the variant).
951 870dc44c Iustin Pop

952 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
953 870dc44c Iustin Pop

954 870dc44c Iustin Pop
    """
955 870dc44c Iustin Pop
    return cls.SplitNameVariant(name)[0]
956 870dc44c Iustin Pop
957 870dc44c Iustin Pop
  @classmethod
958 870dc44c Iustin Pop
  def GetVariant(cls, name):
959 870dc44c Iustin Pop
    """Returns the variant the os (without the base name).
960 870dc44c Iustin Pop

961 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
962 870dc44c Iustin Pop

963 870dc44c Iustin Pop
    """
964 870dc44c Iustin Pop
    return cls.SplitNameVariant(name)[1]
965 870dc44c Iustin Pop
966 7c0d6283 Michael Hanselmann
967 ec29fe40 Iustin Pop
class Node(TaggableObject):
968 a8083063 Iustin Pop
  """Config object representing a node."""
969 154b9580 Balazs Lecz
  __slots__ = [
970 ec29fe40 Iustin Pop
    "name",
971 ec29fe40 Iustin Pop
    "primary_ip",
972 ec29fe40 Iustin Pop
    "secondary_ip",
973 be1fa613 Iustin Pop
    "serial_no",
974 8b8b8b81 Iustin Pop
    "master_candidate",
975 fc0fe88c Iustin Pop
    "offline",
976 af64c0ea Iustin Pop
    "drained",
977 f936c153 Iustin Pop
    "group",
978 490acd18 Iustin Pop
    "master_capable",
979 490acd18 Iustin Pop
    "vm_capable",
980 095e71aa Renรฉ Nussbaumer
    "ndparams",
981 25124d4a Renรฉ Nussbaumer
    "powered",
982 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
983 a8083063 Iustin Pop
984 490acd18 Iustin Pop
  def UpgradeConfig(self):
985 490acd18 Iustin Pop
    """Fill defaults for missing configuration values.
986 490acd18 Iustin Pop

987 490acd18 Iustin Pop
    """
988 b459a848 Andrea Spadaccini
    # pylint: disable=E0203
989 490acd18 Iustin Pop
    # because these are "defined" via slots, not manually
990 490acd18 Iustin Pop
    if self.master_capable is None:
991 490acd18 Iustin Pop
      self.master_capable = True
992 490acd18 Iustin Pop
993 490acd18 Iustin Pop
    if self.vm_capable is None:
994 490acd18 Iustin Pop
      self.vm_capable = True
995 490acd18 Iustin Pop
996 095e71aa Renรฉ Nussbaumer
    if self.ndparams is None:
997 095e71aa Renรฉ Nussbaumer
      self.ndparams = {}
998 095e71aa Renรฉ Nussbaumer
999 25124d4a Renรฉ Nussbaumer
    if self.powered is None:
1000 25124d4a Renรฉ Nussbaumer
      self.powered = True
1001 25124d4a Renรฉ Nussbaumer
1002 a8083063 Iustin Pop
1003 1ffd2673 Michael Hanselmann
class NodeGroup(TaggableObject):
1004 24a3707f Guido Trotter
  """Config object representing a node group."""
1005 24a3707f Guido Trotter
  __slots__ = [
1006 24a3707f Guido Trotter
    "name",
1007 24a3707f Guido Trotter
    "members",
1008 095e71aa Renรฉ Nussbaumer
    "ndparams",
1009 e11a1b77 Adeodato Simo
    "serial_no",
1010 90e99856 Adeodato Simo
    "alloc_policy",
1011 24a3707f Guido Trotter
    ] + _TIMESTAMPS + _UUID
1012 24a3707f Guido Trotter
1013 24a3707f Guido Trotter
  def ToDict(self):
1014 24a3707f Guido Trotter
    """Custom function for nodegroup.
1015 24a3707f Guido Trotter

1016 c60abd62 Guido Trotter
    This discards the members object, which gets recalculated and is only kept
1017 c60abd62 Guido Trotter
    in memory.
1018 24a3707f Guido Trotter

1019 24a3707f Guido Trotter
    """
1020 24a3707f Guido Trotter
    mydict = super(NodeGroup, self).ToDict()
1021 24a3707f Guido Trotter
    del mydict["members"]
1022 24a3707f Guido Trotter
    return mydict
1023 24a3707f Guido Trotter
1024 24a3707f Guido Trotter
  @classmethod
1025 24a3707f Guido Trotter
  def FromDict(cls, val):
1026 24a3707f Guido Trotter
    """Custom function for nodegroup.
1027 24a3707f Guido Trotter

1028 24a3707f Guido Trotter
    The members slot is initialized to an empty list, upon deserialization.
1029 24a3707f Guido Trotter

1030 24a3707f Guido Trotter
    """
1031 24a3707f Guido Trotter
    obj = super(NodeGroup, cls).FromDict(val)
1032 24a3707f Guido Trotter
    obj.members = []
1033 24a3707f Guido Trotter
    return obj
1034 24a3707f Guido Trotter
1035 095e71aa Renรฉ Nussbaumer
  def UpgradeConfig(self):
1036 095e71aa Renรฉ Nussbaumer
    """Fill defaults for missing configuration values.
1037 095e71aa Renรฉ Nussbaumer

1038 095e71aa Renรฉ Nussbaumer
    """
1039 095e71aa Renรฉ Nussbaumer
    if self.ndparams is None:
1040 095e71aa Renรฉ Nussbaumer
      self.ndparams = {}
1041 095e71aa Renรฉ Nussbaumer
1042 e11a1b77 Adeodato Simo
    if self.serial_no is None:
1043 e11a1b77 Adeodato Simo
      self.serial_no = 1
1044 e11a1b77 Adeodato Simo
1045 90e99856 Adeodato Simo
    if self.alloc_policy is None:
1046 90e99856 Adeodato Simo
      self.alloc_policy = constants.ALLOC_POLICY_PREFERRED
1047 90e99856 Adeodato Simo
1048 e11a1b77 Adeodato Simo
    # We only update mtime, and not ctime, since we would not be able to provide
1049 e11a1b77 Adeodato Simo
    # a correct value for creation time.
1050 e11a1b77 Adeodato Simo
    if self.mtime is None:
1051 e11a1b77 Adeodato Simo
      self.mtime = time.time()
1052 e11a1b77 Adeodato Simo
1053 095e71aa Renรฉ Nussbaumer
  def FillND(self, node):
1054 ce523de1 Michael Hanselmann
    """Return filled out ndparams for L{objects.Node}
1055 095e71aa Renรฉ Nussbaumer

1056 095e71aa Renรฉ Nussbaumer
    @type node: L{objects.Node}
1057 095e71aa Renรฉ Nussbaumer
    @param node: A Node object to fill
1058 095e71aa Renรฉ Nussbaumer
    @return a copy of the node's ndparams with defaults filled
1059 095e71aa Renรฉ Nussbaumer

1060 095e71aa Renรฉ Nussbaumer
    """
1061 095e71aa Renรฉ Nussbaumer
    return self.SimpleFillND(node.ndparams)
1062 095e71aa Renรฉ Nussbaumer
1063 095e71aa Renรฉ Nussbaumer
  def SimpleFillND(self, ndparams):
1064 095e71aa Renรฉ Nussbaumer
    """Fill a given ndparams dict with defaults.
1065 095e71aa Renรฉ Nussbaumer

1066 095e71aa Renรฉ Nussbaumer
    @type ndparams: dict
1067 095e71aa Renรฉ Nussbaumer
    @param ndparams: the dict to fill
1068 095e71aa Renรฉ Nussbaumer
    @rtype: dict
1069 095e71aa Renรฉ Nussbaumer
    @return: a copy of the passed in ndparams with missing keys filled
1070 e6e88de6 Adeodato Simo
        from the node group defaults
1071 095e71aa Renรฉ Nussbaumer

1072 095e71aa Renรฉ Nussbaumer
    """
1073 095e71aa Renรฉ Nussbaumer
    return FillDict(self.ndparams, ndparams)
1074 095e71aa Renรฉ Nussbaumer
1075 24a3707f Guido Trotter
1076 ec29fe40 Iustin Pop
class Cluster(TaggableObject):
1077 a8083063 Iustin Pop
  """Config object representing the cluster."""
1078 154b9580 Balazs Lecz
  __slots__ = [
1079 a8083063 Iustin Pop
    "serial_no",
1080 a8083063 Iustin Pop
    "rsahostkeypub",
1081 a8083063 Iustin Pop
    "highest_used_port",
1082 b2fddf63 Iustin Pop
    "tcpudp_port_pool",
1083 a8083063 Iustin Pop
    "mac_prefix",
1084 a8083063 Iustin Pop
    "volume_group_name",
1085 999b183c Iustin Pop
    "reserved_lvs",
1086 9e33896b Luca Bigliardi
    "drbd_usermode_helper",
1087 a8083063 Iustin Pop
    "default_bridge",
1088 02691904 Alexander Schreiber
    "default_hypervisor",
1089 f6bd6e98 Michael Hanselmann
    "master_node",
1090 f6bd6e98 Michael Hanselmann
    "master_ip",
1091 f6bd6e98 Michael Hanselmann
    "master_netdev",
1092 5a8648eb Andrea Spadaccini
    "master_netmask",
1093 f6bd6e98 Michael Hanselmann
    "cluster_name",
1094 f6bd6e98 Michael Hanselmann
    "file_storage_dir",
1095 4b97f902 Apollon Oikonomopoulos
    "shared_file_storage_dir",
1096 e69d05fd Iustin Pop
    "enabled_hypervisors",
1097 5bf7b5cf Iustin Pop
    "hvparams",
1098 17463d22 Renรฉ Nussbaumer
    "os_hvp",
1099 5bf7b5cf Iustin Pop
    "beparams",
1100 1bdcbbab Iustin Pop
    "osparams",
1101 c8fcde47 Guido Trotter
    "nicparams",
1102 095e71aa Renรฉ Nussbaumer
    "ndparams",
1103 4b7735f9 Iustin Pop
    "candidate_pool_size",
1104 b86a6bcd Guido Trotter
    "modify_etc_hosts",
1105 b989b9d9 Ken Wehr
    "modify_ssh_setup",
1106 3953242f Iustin Pop
    "maintain_node_health",
1107 4437d889 Balazs Lecz
    "uid_pool",
1108 bf4af505 Apollon Oikonomopoulos
    "default_iallocator",
1109 87b2cd45 Iustin Pop
    "hidden_os",
1110 87b2cd45 Iustin Pop
    "blacklisted_os",
1111 2f20d07b Manuel Franceschini
    "primary_ip_family",
1112 3d914585 Renรฉ Nussbaumer
    "prealloc_wipe_disks",
1113 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
1114 a8083063 Iustin Pop
1115 b86a6bcd Guido Trotter
  def UpgradeConfig(self):
1116 b86a6bcd Guido Trotter
    """Fill defaults for missing configuration values.
1117 b86a6bcd Guido Trotter

1118 b86a6bcd Guido Trotter
    """
1119 b459a848 Andrea Spadaccini
    # pylint: disable=E0203
1120 fe267188 Iustin Pop
    # because these are "defined" via slots, not manually
1121 c1b42c18 Guido Trotter
    if self.hvparams is None:
1122 c1b42c18 Guido Trotter
      self.hvparams = constants.HVC_DEFAULTS
1123 c1b42c18 Guido Trotter
    else:
1124 c1b42c18 Guido Trotter
      for hypervisor in self.hvparams:
1125 abe609b2 Guido Trotter
        self.hvparams[hypervisor] = FillDict(
1126 c1b42c18 Guido Trotter
            constants.HVC_DEFAULTS[hypervisor], self.hvparams[hypervisor])
1127 c1b42c18 Guido Trotter
1128 17463d22 Renรฉ Nussbaumer
    if self.os_hvp is None:
1129 17463d22 Renรฉ Nussbaumer
      self.os_hvp = {}
1130 17463d22 Renรฉ Nussbaumer
1131 1bdcbbab Iustin Pop
    # osparams added before 2.2
1132 1bdcbbab Iustin Pop
    if self.osparams is None:
1133 1bdcbbab Iustin Pop
      self.osparams = {}
1134 1bdcbbab Iustin Pop
1135 095e71aa Renรฉ Nussbaumer
    if self.ndparams is None:
1136 095e71aa Renรฉ Nussbaumer
      self.ndparams = constants.NDC_DEFAULTS
1137 095e71aa Renรฉ Nussbaumer
1138 6e34b628 Guido Trotter
    self.beparams = UpgradeGroupedParams(self.beparams,
1139 6e34b628 Guido Trotter
                                         constants.BEC_DEFAULTS)
1140 c8fcde47 Guido Trotter
    migrate_default_bridge = not self.nicparams
1141 c8fcde47 Guido Trotter
    self.nicparams = UpgradeGroupedParams(self.nicparams,
1142 c8fcde47 Guido Trotter
                                          constants.NICC_DEFAULTS)
1143 c8fcde47 Guido Trotter
    if migrate_default_bridge:
1144 c8fcde47 Guido Trotter
      self.nicparams[constants.PP_DEFAULT][constants.NIC_LINK] = \
1145 c8fcde47 Guido Trotter
        self.default_bridge
1146 c1b42c18 Guido Trotter
1147 b86a6bcd Guido Trotter
    if self.modify_etc_hosts is None:
1148 b86a6bcd Guido Trotter
      self.modify_etc_hosts = True
1149 b86a6bcd Guido Trotter
1150 b989b9d9 Ken Wehr
    if self.modify_ssh_setup is None:
1151 b989b9d9 Ken Wehr
      self.modify_ssh_setup = True
1152 b989b9d9 Ken Wehr
1153 73f1d185 Stephen Shirley
    # default_bridge is no longer used in 2.1. The slot is left there to
1154 90d118fd Guido Trotter
    # support auto-upgrading. It can be removed once we decide to deprecate
1155 90d118fd Guido Trotter
    # upgrading straight from 2.0.
1156 9b31ca85 Guido Trotter
    if self.default_bridge is not None:
1157 9b31ca85 Guido Trotter
      self.default_bridge = None
1158 9b31ca85 Guido Trotter
1159 90d118fd Guido Trotter
    # default_hypervisor is just the first enabled one in 2.1. This slot and
1160 90d118fd Guido Trotter
    # code can be removed once upgrading straight from 2.0 is deprecated.
1161 066f465d Guido Trotter
    if self.default_hypervisor is not None:
1162 016d04b3 Michael Hanselmann
      self.enabled_hypervisors = ([self.default_hypervisor] +
1163 066f465d Guido Trotter
        [hvname for hvname in self.enabled_hypervisors
1164 016d04b3 Michael Hanselmann
         if hvname != self.default_hypervisor])
1165 066f465d Guido Trotter
      self.default_hypervisor = None
1166 066f465d Guido Trotter
1167 3953242f Iustin Pop
    # maintain_node_health added after 2.1.1
1168 3953242f Iustin Pop
    if self.maintain_node_health is None:
1169 3953242f Iustin Pop
      self.maintain_node_health = False
1170 3953242f Iustin Pop
1171 4437d889 Balazs Lecz
    if self.uid_pool is None:
1172 4437d889 Balazs Lecz
      self.uid_pool = []
1173 4437d889 Balazs Lecz
1174 bf4af505 Apollon Oikonomopoulos
    if self.default_iallocator is None:
1175 bf4af505 Apollon Oikonomopoulos
      self.default_iallocator = ""
1176 bf4af505 Apollon Oikonomopoulos
1177 999b183c Iustin Pop
    # reserved_lvs added before 2.2
1178 999b183c Iustin Pop
    if self.reserved_lvs is None:
1179 999b183c Iustin Pop
      self.reserved_lvs = []
1180 999b183c Iustin Pop
1181 546b1111 Iustin Pop
    # hidden and blacklisted operating systems added before 2.2.1
1182 87b2cd45 Iustin Pop
    if self.hidden_os is None:
1183 87b2cd45 Iustin Pop
      self.hidden_os = []
1184 546b1111 Iustin Pop
1185 87b2cd45 Iustin Pop
    if self.blacklisted_os is None:
1186 87b2cd45 Iustin Pop
      self.blacklisted_os = []
1187 546b1111 Iustin Pop
1188 f4c9af7a Guido Trotter
    # primary_ip_family added before 2.3
1189 f4c9af7a Guido Trotter
    if self.primary_ip_family is None:
1190 f4c9af7a Guido Trotter
      self.primary_ip_family = AF_INET
1191 f4c9af7a Guido Trotter
1192 3d914585 Renรฉ Nussbaumer
    if self.prealloc_wipe_disks is None:
1193 3d914585 Renรฉ Nussbaumer
      self.prealloc_wipe_disks = False
1194 3d914585 Renรฉ Nussbaumer
1195 e8f472d1 Iustin Pop
    # shared_file_storage_dir added before 2.5
1196 e8f472d1 Iustin Pop
    if self.shared_file_storage_dir is None:
1197 e8f472d1 Iustin Pop
      self.shared_file_storage_dir = ""
1198 e8f472d1 Iustin Pop
1199 319856a9 Michael Hanselmann
  def ToDict(self):
1200 319856a9 Michael Hanselmann
    """Custom function for cluster.
1201 319856a9 Michael Hanselmann

1202 319856a9 Michael Hanselmann
    """
1203 b60ae2ca Iustin Pop
    mydict = super(Cluster, self).ToDict()
1204 319856a9 Michael Hanselmann
    mydict["tcpudp_port_pool"] = list(self.tcpudp_port_pool)
1205 319856a9 Michael Hanselmann
    return mydict
1206 319856a9 Michael Hanselmann
1207 319856a9 Michael Hanselmann
  @classmethod
1208 319856a9 Michael Hanselmann
  def FromDict(cls, val):
1209 319856a9 Michael Hanselmann
    """Custom function for cluster.
1210 319856a9 Michael Hanselmann

1211 319856a9 Michael Hanselmann
    """
1212 b60ae2ca Iustin Pop
    obj = super(Cluster, cls).FromDict(val)
1213 319856a9 Michael Hanselmann
    if not isinstance(obj.tcpudp_port_pool, set):
1214 319856a9 Michael Hanselmann
      obj.tcpudp_port_pool = set(obj.tcpudp_port_pool)
1215 319856a9 Michael Hanselmann
    return obj
1216 319856a9 Michael Hanselmann
1217 d63479b5 Iustin Pop
  def GetHVDefaults(self, hypervisor, os_name=None, skip_keys=None):
1218 d63479b5 Iustin Pop
    """Get the default hypervisor parameters for the cluster.
1219 d63479b5 Iustin Pop

1220 d63479b5 Iustin Pop
    @param hypervisor: the hypervisor name
1221 d63479b5 Iustin Pop
    @param os_name: if specified, we'll also update the defaults for this OS
1222 d63479b5 Iustin Pop
    @param skip_keys: if passed, list of keys not to use
1223 d63479b5 Iustin Pop
    @return: the defaults dict
1224 d63479b5 Iustin Pop

1225 d63479b5 Iustin Pop
    """
1226 d63479b5 Iustin Pop
    if skip_keys is None:
1227 d63479b5 Iustin Pop
      skip_keys = []
1228 d63479b5 Iustin Pop
1229 d63479b5 Iustin Pop
    fill_stack = [self.hvparams.get(hypervisor, {})]
1230 d63479b5 Iustin Pop
    if os_name is not None:
1231 d63479b5 Iustin Pop
      os_hvp = self.os_hvp.get(os_name, {}).get(hypervisor, {})
1232 d63479b5 Iustin Pop
      fill_stack.append(os_hvp)
1233 d63479b5 Iustin Pop
1234 d63479b5 Iustin Pop
    ret_dict = {}
1235 d63479b5 Iustin Pop
    for o_dict in fill_stack:
1236 d63479b5 Iustin Pop
      ret_dict = FillDict(ret_dict, o_dict, skip_keys=skip_keys)
1237 d63479b5 Iustin Pop
1238 d63479b5 Iustin Pop
    return ret_dict
1239 d63479b5 Iustin Pop
1240 73e0328b Iustin Pop
  def SimpleFillHV(self, hv_name, os_name, hvparams, skip_globals=False):
1241 73e0328b Iustin Pop
    """Fill a given hvparams dict with cluster defaults.
1242 73e0328b Iustin Pop

1243 73e0328b Iustin Pop
    @type hv_name: string
1244 73e0328b Iustin Pop
    @param hv_name: the hypervisor to use
1245 73e0328b Iustin Pop
    @type os_name: string
1246 73e0328b Iustin Pop
    @param os_name: the OS to use for overriding the hypervisor defaults
1247 73e0328b Iustin Pop
    @type skip_globals: boolean
1248 73e0328b Iustin Pop
    @param skip_globals: if True, the global hypervisor parameters will
1249 73e0328b Iustin Pop
        not be filled
1250 73e0328b Iustin Pop
    @rtype: dict
1251 73e0328b Iustin Pop
    @return: a copy of the given hvparams with missing keys filled from
1252 73e0328b Iustin Pop
        the cluster defaults
1253 73e0328b Iustin Pop

1254 73e0328b Iustin Pop
    """
1255 73e0328b Iustin Pop
    if skip_globals:
1256 73e0328b Iustin Pop
      skip_keys = constants.HVC_GLOBALS
1257 73e0328b Iustin Pop
    else:
1258 73e0328b Iustin Pop
      skip_keys = []
1259 73e0328b Iustin Pop
1260 73e0328b Iustin Pop
    def_dict = self.GetHVDefaults(hv_name, os_name, skip_keys=skip_keys)
1261 73e0328b Iustin Pop
    return FillDict(def_dict, hvparams, skip_keys=skip_keys)
1262 d63479b5 Iustin Pop
1263 7736a5f2 Iustin Pop
  def FillHV(self, instance, skip_globals=False):
1264 73e0328b Iustin Pop
    """Fill an instance's hvparams dict with cluster defaults.
1265 5bf7b5cf Iustin Pop

1266 a2a24f4c Guido Trotter
    @type instance: L{objects.Instance}
1267 5bf7b5cf Iustin Pop
    @param instance: the instance parameter to fill
1268 7736a5f2 Iustin Pop
    @type skip_globals: boolean
1269 7736a5f2 Iustin Pop
    @param skip_globals: if True, the global hypervisor parameters will
1270 7736a5f2 Iustin Pop
        not be filled
1271 5bf7b5cf Iustin Pop
    @rtype: dict
1272 5bf7b5cf Iustin Pop
    @return: a copy of the instance's hvparams with missing keys filled from
1273 5bf7b5cf Iustin Pop
        the cluster defaults
1274 5bf7b5cf Iustin Pop

1275 5bf7b5cf Iustin Pop
    """
1276 73e0328b Iustin Pop
    return self.SimpleFillHV(instance.hypervisor, instance.os,
1277 73e0328b Iustin Pop
                             instance.hvparams, skip_globals)
1278 17463d22 Renรฉ Nussbaumer
1279 73e0328b Iustin Pop
  def SimpleFillBE(self, beparams):
1280 73e0328b Iustin Pop
    """Fill a given beparams dict with cluster defaults.
1281 73e0328b Iustin Pop

1282 06596a60 Guido Trotter
    @type beparams: dict
1283 06596a60 Guido Trotter
    @param beparams: the dict to fill
1284 73e0328b Iustin Pop
    @rtype: dict
1285 73e0328b Iustin Pop
    @return: a copy of the passed in beparams with missing keys filled
1286 73e0328b Iustin Pop
        from the cluster defaults
1287 73e0328b Iustin Pop

1288 73e0328b Iustin Pop
    """
1289 73e0328b Iustin Pop
    return FillDict(self.beparams.get(constants.PP_DEFAULT, {}), beparams)
1290 5bf7b5cf Iustin Pop
1291 5bf7b5cf Iustin Pop
  def FillBE(self, instance):
1292 73e0328b Iustin Pop
    """Fill an instance's beparams dict with cluster defaults.
1293 5bf7b5cf Iustin Pop

1294 a2a24f4c Guido Trotter
    @type instance: L{objects.Instance}
1295 5bf7b5cf Iustin Pop
    @param instance: the instance parameter to fill
1296 5bf7b5cf Iustin Pop
    @rtype: dict
1297 5bf7b5cf Iustin Pop
    @return: a copy of the instance's beparams with missing keys filled from
1298 5bf7b5cf Iustin Pop
        the cluster defaults
1299 5bf7b5cf Iustin Pop

1300 5bf7b5cf Iustin Pop
    """
1301 73e0328b Iustin Pop
    return self.SimpleFillBE(instance.beparams)
1302 73e0328b Iustin Pop
1303 73e0328b Iustin Pop
  def SimpleFillNIC(self, nicparams):
1304 73e0328b Iustin Pop
    """Fill a given nicparams dict with cluster defaults.
1305 73e0328b Iustin Pop

1306 06596a60 Guido Trotter
    @type nicparams: dict
1307 06596a60 Guido Trotter
    @param nicparams: the dict to fill
1308 73e0328b Iustin Pop
    @rtype: dict
1309 73e0328b Iustin Pop
    @return: a copy of the passed in nicparams with missing keys filled
1310 73e0328b Iustin Pop
        from the cluster defaults
1311 73e0328b Iustin Pop

1312 73e0328b Iustin Pop
    """
1313 73e0328b Iustin Pop
    return FillDict(self.nicparams.get(constants.PP_DEFAULT, {}), nicparams)
1314 5bf7b5cf Iustin Pop
1315 1bdcbbab Iustin Pop
  def SimpleFillOS(self, os_name, os_params):
1316 1bdcbbab Iustin Pop
    """Fill an instance's osparams dict with cluster defaults.
1317 1bdcbbab Iustin Pop

1318 1bdcbbab Iustin Pop
    @type os_name: string
1319 1bdcbbab Iustin Pop
    @param os_name: the OS name to use
1320 1bdcbbab Iustin Pop
    @type os_params: dict
1321 1bdcbbab Iustin Pop
    @param os_params: the dict to fill with default values
1322 1bdcbbab Iustin Pop
    @rtype: dict
1323 1bdcbbab Iustin Pop
    @return: a copy of the instance's osparams with missing keys filled from
1324 1bdcbbab Iustin Pop
        the cluster defaults
1325 1bdcbbab Iustin Pop

1326 1bdcbbab Iustin Pop
    """
1327 1bdcbbab Iustin Pop
    name_only = os_name.split("+", 1)[0]
1328 1bdcbbab Iustin Pop
    # base OS
1329 1bdcbbab Iustin Pop
    result = self.osparams.get(name_only, {})
1330 1bdcbbab Iustin Pop
    # OS with variant
1331 1bdcbbab Iustin Pop
    result = FillDict(result, self.osparams.get(os_name, {}))
1332 1bdcbbab Iustin Pop
    # specified params
1333 1bdcbbab Iustin Pop
    return FillDict(result, os_params)
1334 1bdcbbab Iustin Pop
1335 095e71aa Renรฉ Nussbaumer
  def FillND(self, node, nodegroup):
1336 ce523de1 Michael Hanselmann
    """Return filled out ndparams for L{objects.NodeGroup} and L{objects.Node}
1337 095e71aa Renรฉ Nussbaumer

1338 095e71aa Renรฉ Nussbaumer
    @type node: L{objects.Node}
1339 095e71aa Renรฉ Nussbaumer
    @param node: A Node object to fill
1340 095e71aa Renรฉ Nussbaumer
    @type nodegroup: L{objects.NodeGroup}
1341 095e71aa Renรฉ Nussbaumer
    @param nodegroup: A Node object to fill
1342 095e71aa Renรฉ Nussbaumer
    @return a copy of the node's ndparams with defaults filled
1343 095e71aa Renรฉ Nussbaumer

1344 095e71aa Renรฉ Nussbaumer
    """
1345 095e71aa Renรฉ Nussbaumer
    return self.SimpleFillND(nodegroup.FillND(node))
1346 095e71aa Renรฉ Nussbaumer
1347 095e71aa Renรฉ Nussbaumer
  def SimpleFillND(self, ndparams):
1348 095e71aa Renรฉ Nussbaumer
    """Fill a given ndparams dict with defaults.
1349 095e71aa Renรฉ Nussbaumer

1350 095e71aa Renรฉ Nussbaumer
    @type ndparams: dict
1351 095e71aa Renรฉ Nussbaumer
    @param ndparams: the dict to fill
1352 095e71aa Renรฉ Nussbaumer
    @rtype: dict
1353 095e71aa Renรฉ Nussbaumer
    @return: a copy of the passed in ndparams with missing keys filled
1354 095e71aa Renรฉ Nussbaumer
        from the cluster defaults
1355 095e71aa Renรฉ Nussbaumer

1356 095e71aa Renรฉ Nussbaumer
    """
1357 095e71aa Renรฉ Nussbaumer
    return FillDict(self.ndparams, ndparams)
1358 095e71aa Renรฉ Nussbaumer
1359 5c947f38 Iustin Pop
1360 96acbc09 Michael Hanselmann
class BlockDevStatus(ConfigObject):
1361 96acbc09 Michael Hanselmann
  """Config object representing the status of a block device."""
1362 96acbc09 Michael Hanselmann
  __slots__ = [
1363 96acbc09 Michael Hanselmann
    "dev_path",
1364 96acbc09 Michael Hanselmann
    "major",
1365 96acbc09 Michael Hanselmann
    "minor",
1366 96acbc09 Michael Hanselmann
    "sync_percent",
1367 96acbc09 Michael Hanselmann
    "estimated_time",
1368 96acbc09 Michael Hanselmann
    "is_degraded",
1369 f208978a Michael Hanselmann
    "ldisk_status",
1370 96acbc09 Michael Hanselmann
    ]
1371 96acbc09 Michael Hanselmann
1372 96acbc09 Michael Hanselmann
1373 2d76b580 Michael Hanselmann
class ImportExportStatus(ConfigObject):
1374 2d76b580 Michael Hanselmann
  """Config object representing the status of an import or export."""
1375 2d76b580 Michael Hanselmann
  __slots__ = [
1376 2d76b580 Michael Hanselmann
    "recent_output",
1377 2d76b580 Michael Hanselmann
    "listen_port",
1378 2d76b580 Michael Hanselmann
    "connected",
1379 c08d76f5 Michael Hanselmann
    "progress_mbytes",
1380 c08d76f5 Michael Hanselmann
    "progress_throughput",
1381 c08d76f5 Michael Hanselmann
    "progress_eta",
1382 c08d76f5 Michael Hanselmann
    "progress_percent",
1383 2d76b580 Michael Hanselmann
    "exit_status",
1384 2d76b580 Michael Hanselmann
    "error_message",
1385 2d76b580 Michael Hanselmann
    ] + _TIMESTAMPS
1386 2d76b580 Michael Hanselmann
1387 2d76b580 Michael Hanselmann
1388 eb630f50 Michael Hanselmann
class ImportExportOptions(ConfigObject):
1389 eb630f50 Michael Hanselmann
  """Options for import/export daemon
1390 eb630f50 Michael Hanselmann

1391 eb630f50 Michael Hanselmann
  @ivar key_name: X509 key name (None for cluster certificate)
1392 eb630f50 Michael Hanselmann
  @ivar ca_pem: Remote peer CA in PEM format (None for cluster certificate)
1393 a5310c2a Michael Hanselmann
  @ivar compress: Compression method (one of L{constants.IEC_ALL})
1394 af1d39b1 Michael Hanselmann
  @ivar magic: Used to ensure the connection goes to the right disk
1395 855d2fc7 Michael Hanselmann
  @ivar ipv6: Whether to use IPv6
1396 4478301b Michael Hanselmann
  @ivar connect_timeout: Number of seconds for establishing connection
1397 eb630f50 Michael Hanselmann

1398 eb630f50 Michael Hanselmann
  """
1399 eb630f50 Michael Hanselmann
  __slots__ = [
1400 eb630f50 Michael Hanselmann
    "key_name",
1401 eb630f50 Michael Hanselmann
    "ca_pem",
1402 a5310c2a Michael Hanselmann
    "compress",
1403 af1d39b1 Michael Hanselmann
    "magic",
1404 855d2fc7 Michael Hanselmann
    "ipv6",
1405 4478301b Michael Hanselmann
    "connect_timeout",
1406 eb630f50 Michael Hanselmann
    ]
1407 eb630f50 Michael Hanselmann
1408 eb630f50 Michael Hanselmann
1409 18d750b9 Guido Trotter
class ConfdRequest(ConfigObject):
1410 18d750b9 Guido Trotter
  """Object holding a confd request.
1411 18d750b9 Guido Trotter

1412 18d750b9 Guido Trotter
  @ivar protocol: confd protocol version
1413 18d750b9 Guido Trotter
  @ivar type: confd query type
1414 18d750b9 Guido Trotter
  @ivar query: query request
1415 18d750b9 Guido Trotter
  @ivar rsalt: requested reply salt
1416 18d750b9 Guido Trotter

1417 18d750b9 Guido Trotter
  """
1418 18d750b9 Guido Trotter
  __slots__ = [
1419 18d750b9 Guido Trotter
    "protocol",
1420 18d750b9 Guido Trotter
    "type",
1421 18d750b9 Guido Trotter
    "query",
1422 18d750b9 Guido Trotter
    "rsalt",
1423 18d750b9 Guido Trotter
    ]
1424 18d750b9 Guido Trotter
1425 18d750b9 Guido Trotter
1426 18d750b9 Guido Trotter
class ConfdReply(ConfigObject):
1427 18d750b9 Guido Trotter
  """Object holding a confd reply.
1428 18d750b9 Guido Trotter

1429 18d750b9 Guido Trotter
  @ivar protocol: confd protocol version
1430 18d750b9 Guido Trotter
  @ivar status: reply status code (ok, error)
1431 18d750b9 Guido Trotter
  @ivar answer: confd query reply
1432 18d750b9 Guido Trotter
  @ivar serial: configuration serial number
1433 18d750b9 Guido Trotter

1434 18d750b9 Guido Trotter
  """
1435 18d750b9 Guido Trotter
  __slots__ = [
1436 18d750b9 Guido Trotter
    "protocol",
1437 18d750b9 Guido Trotter
    "status",
1438 18d750b9 Guido Trotter
    "answer",
1439 18d750b9 Guido Trotter
    "serial",
1440 18d750b9 Guido Trotter
    ]
1441 18d750b9 Guido Trotter
1442 18d750b9 Guido Trotter
1443 707f23b5 Michael Hanselmann
class QueryFieldDefinition(ConfigObject):
1444 707f23b5 Michael Hanselmann
  """Object holding a query field definition.
1445 707f23b5 Michael Hanselmann

1446 24d6d3e2 Michael Hanselmann
  @ivar name: Field name
1447 707f23b5 Michael Hanselmann
  @ivar title: Human-readable title
1448 707f23b5 Michael Hanselmann
  @ivar kind: Field type
1449 1ae17369 Michael Hanselmann
  @ivar doc: Human-readable description
1450 707f23b5 Michael Hanselmann

1451 707f23b5 Michael Hanselmann
  """
1452 707f23b5 Michael Hanselmann
  __slots__ = [
1453 707f23b5 Michael Hanselmann
    "name",
1454 707f23b5 Michael Hanselmann
    "title",
1455 707f23b5 Michael Hanselmann
    "kind",
1456 1ae17369 Michael Hanselmann
    "doc",
1457 707f23b5 Michael Hanselmann
    ]
1458 707f23b5 Michael Hanselmann
1459 707f23b5 Michael Hanselmann
1460 0538c375 Michael Hanselmann
class _QueryResponseBase(ConfigObject):
1461 0538c375 Michael Hanselmann
  __slots__ = [
1462 0538c375 Michael Hanselmann
    "fields",
1463 0538c375 Michael Hanselmann
    ]
1464 0538c375 Michael Hanselmann
1465 0538c375 Michael Hanselmann
  def ToDict(self):
1466 0538c375 Michael Hanselmann
    """Custom function for serializing.
1467 0538c375 Michael Hanselmann

1468 0538c375 Michael Hanselmann
    """
1469 0538c375 Michael Hanselmann
    mydict = super(_QueryResponseBase, self).ToDict()
1470 0538c375 Michael Hanselmann
    mydict["fields"] = self._ContainerToDicts(mydict["fields"])
1471 0538c375 Michael Hanselmann
    return mydict
1472 0538c375 Michael Hanselmann
1473 0538c375 Michael Hanselmann
  @classmethod
1474 0538c375 Michael Hanselmann
  def FromDict(cls, val):
1475 0538c375 Michael Hanselmann
    """Custom function for de-serializing.
1476 0538c375 Michael Hanselmann

1477 0538c375 Michael Hanselmann
    """
1478 0538c375 Michael Hanselmann
    obj = super(_QueryResponseBase, cls).FromDict(val)
1479 0538c375 Michael Hanselmann
    obj.fields = cls._ContainerFromDicts(obj.fields, list, QueryFieldDefinition)
1480 0538c375 Michael Hanselmann
    return obj
1481 0538c375 Michael Hanselmann
1482 0538c375 Michael Hanselmann
1483 24d6d3e2 Michael Hanselmann
class QueryRequest(ConfigObject):
1484 24d6d3e2 Michael Hanselmann
  """Object holding a query request.
1485 24d6d3e2 Michael Hanselmann

1486 24d6d3e2 Michael Hanselmann
  """
1487 24d6d3e2 Michael Hanselmann
  __slots__ = [
1488 24d6d3e2 Michael Hanselmann
    "what",
1489 24d6d3e2 Michael Hanselmann
    "fields",
1490 2e5c33db Iustin Pop
    "qfilter",
1491 24d6d3e2 Michael Hanselmann
    ]
1492 24d6d3e2 Michael Hanselmann
1493 24d6d3e2 Michael Hanselmann
1494 0538c375 Michael Hanselmann
class QueryResponse(_QueryResponseBase):
1495 24d6d3e2 Michael Hanselmann
  """Object holding the response to a query.
1496 24d6d3e2 Michael Hanselmann

1497 24d6d3e2 Michael Hanselmann
  @ivar fields: List of L{QueryFieldDefinition} objects
1498 24d6d3e2 Michael Hanselmann
  @ivar data: Requested data
1499 24d6d3e2 Michael Hanselmann

1500 24d6d3e2 Michael Hanselmann
  """
1501 24d6d3e2 Michael Hanselmann
  __slots__ = [
1502 24d6d3e2 Michael Hanselmann
    "data",
1503 24d6d3e2 Michael Hanselmann
    ]
1504 24d6d3e2 Michael Hanselmann
1505 24d6d3e2 Michael Hanselmann
1506 24d6d3e2 Michael Hanselmann
class QueryFieldsRequest(ConfigObject):
1507 24d6d3e2 Michael Hanselmann
  """Object holding a request for querying available fields.
1508 24d6d3e2 Michael Hanselmann

1509 24d6d3e2 Michael Hanselmann
  """
1510 24d6d3e2 Michael Hanselmann
  __slots__ = [
1511 24d6d3e2 Michael Hanselmann
    "what",
1512 24d6d3e2 Michael Hanselmann
    "fields",
1513 24d6d3e2 Michael Hanselmann
    ]
1514 24d6d3e2 Michael Hanselmann
1515 24d6d3e2 Michael Hanselmann
1516 0538c375 Michael Hanselmann
class QueryFieldsResponse(_QueryResponseBase):
1517 24d6d3e2 Michael Hanselmann
  """Object holding the response to a query for fields.
1518 24d6d3e2 Michael Hanselmann

1519 24d6d3e2 Michael Hanselmann
  @ivar fields: List of L{QueryFieldDefinition} objects
1520 24d6d3e2 Michael Hanselmann

1521 24d6d3e2 Michael Hanselmann
  """
1522 24d6d3e2 Michael Hanselmann
  __slots__ = [
1523 24d6d3e2 Michael Hanselmann
    ]
1524 24d6d3e2 Michael Hanselmann
1525 24d6d3e2 Michael Hanselmann
1526 6a1434d7 Andrea Spadaccini
class MigrationStatus(ConfigObject):
1527 6a1434d7 Andrea Spadaccini
  """Object holding the status of a migration.
1528 6a1434d7 Andrea Spadaccini

1529 6a1434d7 Andrea Spadaccini
  """
1530 6a1434d7 Andrea Spadaccini
  __slots__ = [
1531 6a1434d7 Andrea Spadaccini
    "status",
1532 6a1434d7 Andrea Spadaccini
    "transferred_ram",
1533 6a1434d7 Andrea Spadaccini
    "total_ram",
1534 6a1434d7 Andrea Spadaccini
    ]
1535 6a1434d7 Andrea Spadaccini
1536 6a1434d7 Andrea Spadaccini
1537 25ce3ec4 Michael Hanselmann
class InstanceConsole(ConfigObject):
1538 25ce3ec4 Michael Hanselmann
  """Object describing how to access the console of an instance.
1539 25ce3ec4 Michael Hanselmann

1540 25ce3ec4 Michael Hanselmann
  """
1541 25ce3ec4 Michael Hanselmann
  __slots__ = [
1542 25ce3ec4 Michael Hanselmann
    "instance",
1543 25ce3ec4 Michael Hanselmann
    "kind",
1544 25ce3ec4 Michael Hanselmann
    "message",
1545 25ce3ec4 Michael Hanselmann
    "host",
1546 25ce3ec4 Michael Hanselmann
    "port",
1547 25ce3ec4 Michael Hanselmann
    "user",
1548 25ce3ec4 Michael Hanselmann
    "command",
1549 25ce3ec4 Michael Hanselmann
    "display",
1550 25ce3ec4 Michael Hanselmann
    ]
1551 25ce3ec4 Michael Hanselmann
1552 25ce3ec4 Michael Hanselmann
  def Validate(self):
1553 25ce3ec4 Michael Hanselmann
    """Validates contents of this object.
1554 25ce3ec4 Michael Hanselmann

1555 25ce3ec4 Michael Hanselmann
    """
1556 25ce3ec4 Michael Hanselmann
    assert self.kind in constants.CONS_ALL, "Unknown console type"
1557 25ce3ec4 Michael Hanselmann
    assert self.instance, "Missing instance name"
1558 4d2cdb5a Andrea Spadaccini
    assert self.message or self.kind in [constants.CONS_SSH,
1559 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1560 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_VNC]
1561 25ce3ec4 Michael Hanselmann
    assert self.host or self.kind == constants.CONS_MESSAGE
1562 25ce3ec4 Michael Hanselmann
    assert self.port or self.kind in [constants.CONS_MESSAGE,
1563 25ce3ec4 Michael Hanselmann
                                      constants.CONS_SSH]
1564 25ce3ec4 Michael Hanselmann
    assert self.user or self.kind in [constants.CONS_MESSAGE,
1565 4d2cdb5a Andrea Spadaccini
                                      constants.CONS_SPICE,
1566 25ce3ec4 Michael Hanselmann
                                      constants.CONS_VNC]
1567 25ce3ec4 Michael Hanselmann
    assert self.command or self.kind in [constants.CONS_MESSAGE,
1568 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1569 25ce3ec4 Michael Hanselmann
                                         constants.CONS_VNC]
1570 25ce3ec4 Michael Hanselmann
    assert self.display or self.kind in [constants.CONS_MESSAGE,
1571 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1572 25ce3ec4 Michael Hanselmann
                                         constants.CONS_SSH]
1573 25ce3ec4 Michael Hanselmann
    return True
1574 25ce3ec4 Michael Hanselmann
1575 25ce3ec4 Michael Hanselmann
1576 a8083063 Iustin Pop
class SerializableConfigParser(ConfigParser.SafeConfigParser):
1577 a8083063 Iustin Pop
  """Simple wrapper over ConfigParse that allows serialization.
1578 a8083063 Iustin Pop

1579 a8083063 Iustin Pop
  This class is basically ConfigParser.SafeConfigParser with two
1580 a8083063 Iustin Pop
  additional methods that allow it to serialize/unserialize to/from a
1581 a8083063 Iustin Pop
  buffer.
1582 a8083063 Iustin Pop

1583 a8083063 Iustin Pop
  """
1584 a8083063 Iustin Pop
  def Dumps(self):
1585 a8083063 Iustin Pop
    """Dump this instance and return the string representation."""
1586 a8083063 Iustin Pop
    buf = StringIO()
1587 a8083063 Iustin Pop
    self.write(buf)
1588 a8083063 Iustin Pop
    return buf.getvalue()
1589 a8083063 Iustin Pop
1590 b39bf4bb Guido Trotter
  @classmethod
1591 b39bf4bb Guido Trotter
  def Loads(cls, data):
1592 a8083063 Iustin Pop
    """Load data from a string."""
1593 a8083063 Iustin Pop
    buf = StringIO(data)
1594 b39bf4bb Guido Trotter
    cfp = cls()
1595 a8083063 Iustin Pop
    cfp.readfp(buf)
1596 a8083063 Iustin Pop
    return cfp