Statistics
| Branch: | Tag: | Revision:

root / lib / objects.py @ 6915fe26

History | View | Annotate | Download (44.1 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 a8083063 Iustin Pop
class ConfigData(ConfigObject):
319 a8083063 Iustin Pop
  """Top-level config object."""
320 3df43542 Guido Trotter
  __slots__ = [
321 3df43542 Guido Trotter
    "version",
322 3df43542 Guido Trotter
    "cluster",
323 3df43542 Guido Trotter
    "nodes",
324 3df43542 Guido Trotter
    "nodegroups",
325 3df43542 Guido Trotter
    "instances",
326 3df43542 Guido Trotter
    "serial_no",
327 3df43542 Guido Trotter
    ] + _TIMESTAMPS
328 a8083063 Iustin Pop
329 ff9c047c Iustin Pop
  def ToDict(self):
330 ff9c047c Iustin Pop
    """Custom function for top-level config data.
331 ff9c047c Iustin Pop

332 ff9c047c Iustin Pop
    This just replaces the list of instances, nodes and the cluster
333 ff9c047c Iustin Pop
    with standard python types.
334 ff9c047c Iustin Pop

335 ff9c047c Iustin Pop
    """
336 ff9c047c Iustin Pop
    mydict = super(ConfigData, self).ToDict()
337 ff9c047c Iustin Pop
    mydict["cluster"] = mydict["cluster"].ToDict()
338 3df43542 Guido Trotter
    for key in "nodes", "instances", "nodegroups":
339 ff9c047c Iustin Pop
      mydict[key] = self._ContainerToDicts(mydict[key])
340 ff9c047c Iustin Pop
341 ff9c047c Iustin Pop
    return mydict
342 ff9c047c Iustin Pop
343 ff9c047c Iustin Pop
  @classmethod
344 ff9c047c Iustin Pop
  def FromDict(cls, val):
345 ff9c047c Iustin Pop
    """Custom function for top-level config data
346 ff9c047c Iustin Pop

347 ff9c047c Iustin Pop
    """
348 ff9c047c Iustin Pop
    obj = super(ConfigData, cls).FromDict(val)
349 ff9c047c Iustin Pop
    obj.cluster = Cluster.FromDict(obj.cluster)
350 ff9c047c Iustin Pop
    obj.nodes = cls._ContainerFromDicts(obj.nodes, dict, Node)
351 ff9c047c Iustin Pop
    obj.instances = cls._ContainerFromDicts(obj.instances, dict, Instance)
352 3df43542 Guido Trotter
    obj.nodegroups = cls._ContainerFromDicts(obj.nodegroups, dict, NodeGroup)
353 ff9c047c Iustin Pop
    return obj
354 ff9c047c Iustin Pop
355 51cb1581 Luca Bigliardi
  def HasAnyDiskOfType(self, dev_type):
356 51cb1581 Luca Bigliardi
    """Check if in there is at disk of the given type in the configuration.
357 51cb1581 Luca Bigliardi

358 51cb1581 Luca Bigliardi
    @type dev_type: L{constants.LDS_BLOCK}
359 51cb1581 Luca Bigliardi
    @param dev_type: the type to look for
360 51cb1581 Luca Bigliardi
    @rtype: boolean
361 51cb1581 Luca Bigliardi
    @return: boolean indicating if a disk of the given type was found or not
362 51cb1581 Luca Bigliardi

363 51cb1581 Luca Bigliardi
    """
364 51cb1581 Luca Bigliardi
    for instance in self.instances.values():
365 51cb1581 Luca Bigliardi
      for disk in instance.disks:
366 51cb1581 Luca Bigliardi
        if disk.IsBasedOnDiskType(dev_type):
367 51cb1581 Luca Bigliardi
          return True
368 51cb1581 Luca Bigliardi
    return False
369 51cb1581 Luca Bigliardi
370 90d726a8 Iustin Pop
  def UpgradeConfig(self):
371 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
372 90d726a8 Iustin Pop

373 90d726a8 Iustin Pop
    """
374 90d726a8 Iustin Pop
    self.cluster.UpgradeConfig()
375 90d726a8 Iustin Pop
    for node in self.nodes.values():
376 90d726a8 Iustin Pop
      node.UpgradeConfig()
377 90d726a8 Iustin Pop
    for instance in self.instances.values():
378 90d726a8 Iustin Pop
      instance.UpgradeConfig()
379 3df43542 Guido Trotter
    if self.nodegroups is None:
380 3df43542 Guido Trotter
      self.nodegroups = {}
381 3df43542 Guido Trotter
    for nodegroup in self.nodegroups.values():
382 3df43542 Guido Trotter
      nodegroup.UpgradeConfig()
383 ee2f0ed4 Luca Bigliardi
    if self.cluster.drbd_usermode_helper is None:
384 ee2f0ed4 Luca Bigliardi
      # To decide if we set an helper let's check if at least one instance has
385 ee2f0ed4 Luca Bigliardi
      # a DRBD disk. This does not cover all the possible scenarios but it
386 ee2f0ed4 Luca Bigliardi
      # gives a good approximation.
387 ee2f0ed4 Luca Bigliardi
      if self.HasAnyDiskOfType(constants.LD_DRBD8):
388 ee2f0ed4 Luca Bigliardi
        self.cluster.drbd_usermode_helper = constants.DEFAULT_DRBD_HELPER
389 90d726a8 Iustin Pop
390 a8083063 Iustin Pop
391 a8083063 Iustin Pop
class NIC(ConfigObject):
392 a8083063 Iustin Pop
  """Config object representing a network card."""
393 1177d70e Guido Trotter
  __slots__ = ["mac", "ip", "nicparams"]
394 a8083063 Iustin Pop
395 255e19d4 Guido Trotter
  @classmethod
396 255e19d4 Guido Trotter
  def CheckParameterSyntax(cls, nicparams):
397 255e19d4 Guido Trotter
    """Check the given parameters for validity.
398 255e19d4 Guido Trotter

399 255e19d4 Guido Trotter
    @type nicparams:  dict
400 255e19d4 Guido Trotter
    @param nicparams: dictionary with parameter names/value
401 255e19d4 Guido Trotter
    @raise errors.ConfigurationError: when a parameter is not valid
402 255e19d4 Guido Trotter

403 255e19d4 Guido Trotter
    """
404 e8448672 Agata Murawska
    if (nicparams[constants.NIC_MODE] not in constants.NIC_VALID_MODES and
405 e8448672 Agata Murawska
        nicparams[constants.NIC_MODE] != constants.VALUE_AUTO):
406 255e19d4 Guido Trotter
      err = "Invalid nic mode: %s" % nicparams[constants.NIC_MODE]
407 255e19d4 Guido Trotter
      raise errors.ConfigurationError(err)
408 255e19d4 Guido Trotter
409 0c9d32c1 Guido Trotter
    if (nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED and
410 255e19d4 Guido Trotter
        not nicparams[constants.NIC_LINK]):
411 255e19d4 Guido Trotter
      err = "Missing bridged nic link"
412 255e19d4 Guido Trotter
      raise errors.ConfigurationError(err)
413 255e19d4 Guido Trotter
414 a8083063 Iustin Pop
415 a8083063 Iustin Pop
class Disk(ConfigObject):
416 a8083063 Iustin Pop
  """Config object representing a block device."""
417 a8083063 Iustin Pop
  __slots__ = ["dev_type", "logical_id", "physical_id",
418 08db7c5c Iustin Pop
               "children", "iv_name", "size", "mode"]
419 a8083063 Iustin Pop
420 a8083063 Iustin Pop
  def CreateOnSecondary(self):
421 a8083063 Iustin Pop
    """Test if this device needs to be created on a secondary node."""
422 00fb8246 Michael Hanselmann
    return self.dev_type in (constants.LD_DRBD8, constants.LD_LV)
423 a8083063 Iustin Pop
424 a8083063 Iustin Pop
  def AssembleOnSecondary(self):
425 a8083063 Iustin Pop
    """Test if this device needs to be assembled on a secondary node."""
426 00fb8246 Michael Hanselmann
    return self.dev_type in (constants.LD_DRBD8, constants.LD_LV)
427 a8083063 Iustin Pop
428 a8083063 Iustin Pop
  def OpenOnSecondary(self):
429 a8083063 Iustin Pop
    """Test if this device needs to be opened on a secondary node."""
430 fe96220b Iustin Pop
    return self.dev_type in (constants.LD_LV,)
431 a8083063 Iustin Pop
432 222f2dd5 Iustin Pop
  def StaticDevPath(self):
433 222f2dd5 Iustin Pop
    """Return the device path if this device type has a static one.
434 222f2dd5 Iustin Pop

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

439 e51db2a6 Iustin Pop
    @warning: The path returned is not a normalized pathname; callers
440 e51db2a6 Iustin Pop
        should check that it is a valid path.
441 e51db2a6 Iustin Pop

442 222f2dd5 Iustin Pop
    """
443 222f2dd5 Iustin Pop
    if self.dev_type == constants.LD_LV:
444 222f2dd5 Iustin Pop
      return "/dev/%s/%s" % (self.logical_id[0], self.logical_id[1])
445 b6135bbc Apollon Oikonomopoulos
    elif self.dev_type == constants.LD_BLOCKDEV:
446 b6135bbc Apollon Oikonomopoulos
      return self.logical_id[1]
447 222f2dd5 Iustin Pop
    return None
448 222f2dd5 Iustin Pop
449 fc1dc9d7 Iustin Pop
  def ChildrenNeeded(self):
450 fc1dc9d7 Iustin Pop
    """Compute the needed number of children for activation.
451 fc1dc9d7 Iustin Pop

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

456 fc1dc9d7 Iustin Pop
    Currently, only DRBD8 supports diskless activation (therefore we
457 fc1dc9d7 Iustin Pop
    return 0), for all other we keep the previous semantics and return
458 fc1dc9d7 Iustin Pop
    -1.
459 fc1dc9d7 Iustin Pop

460 fc1dc9d7 Iustin Pop
    """
461 fc1dc9d7 Iustin Pop
    if self.dev_type == constants.LD_DRBD8:
462 fc1dc9d7 Iustin Pop
      return 0
463 fc1dc9d7 Iustin Pop
    return -1
464 fc1dc9d7 Iustin Pop
465 51cb1581 Luca Bigliardi
  def IsBasedOnDiskType(self, dev_type):
466 51cb1581 Luca Bigliardi
    """Check if the disk or its children are based on the given type.
467 51cb1581 Luca Bigliardi

468 51cb1581 Luca Bigliardi
    @type dev_type: L{constants.LDS_BLOCK}
469 51cb1581 Luca Bigliardi
    @param dev_type: the type to look for
470 51cb1581 Luca Bigliardi
    @rtype: boolean
471 51cb1581 Luca Bigliardi
    @return: boolean indicating if a device of the given type was found or not
472 51cb1581 Luca Bigliardi

473 51cb1581 Luca Bigliardi
    """
474 51cb1581 Luca Bigliardi
    if self.children:
475 51cb1581 Luca Bigliardi
      for child in self.children:
476 51cb1581 Luca Bigliardi
        if child.IsBasedOnDiskType(dev_type):
477 51cb1581 Luca Bigliardi
          return True
478 51cb1581 Luca Bigliardi
    return self.dev_type == dev_type
479 51cb1581 Luca Bigliardi
480 a8083063 Iustin Pop
  def GetNodes(self, node):
481 a8083063 Iustin Pop
    """This function returns the nodes this device lives on.
482 a8083063 Iustin Pop

483 a8083063 Iustin Pop
    Given the node on which the parent of the device lives on (or, in
484 a8083063 Iustin Pop
    case of a top-level device, the primary node of the devices'
485 a8083063 Iustin Pop
    instance), this function will return a list of nodes on which this
486 a8083063 Iustin Pop
    devices needs to (or can) be assembled.
487 a8083063 Iustin Pop

488 a8083063 Iustin Pop
    """
489 b6135bbc Apollon Oikonomopoulos
    if self.dev_type in [constants.LD_LV, constants.LD_FILE,
490 b6135bbc Apollon Oikonomopoulos
                         constants.LD_BLOCKDEV]:
491 a8083063 Iustin Pop
      result = [node]
492 a1f445d3 Iustin Pop
    elif self.dev_type in constants.LDS_DRBD:
493 a8083063 Iustin Pop
      result = [self.logical_id[0], self.logical_id[1]]
494 a8083063 Iustin Pop
      if node not in result:
495 3ecf6786 Iustin Pop
        raise errors.ConfigurationError("DRBD device passed unknown node")
496 a8083063 Iustin Pop
    else:
497 3ecf6786 Iustin Pop
      raise errors.ProgrammerError("Unhandled device type %s" % self.dev_type)
498 a8083063 Iustin Pop
    return result
499 a8083063 Iustin Pop
500 a8083063 Iustin Pop
  def ComputeNodeTree(self, parent_node):
501 a8083063 Iustin Pop
    """Compute the node/disk tree for this disk and its children.
502 a8083063 Iustin Pop

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

509 a8083063 Iustin Pop
    """
510 a8083063 Iustin Pop
    my_nodes = self.GetNodes(parent_node)
511 a8083063 Iustin Pop
    result = [(node, self) for node in my_nodes]
512 a8083063 Iustin Pop
    if not self.children:
513 a8083063 Iustin Pop
      # leaf device
514 a8083063 Iustin Pop
      return result
515 a8083063 Iustin Pop
    for node in my_nodes:
516 a8083063 Iustin Pop
      for child in self.children:
517 a8083063 Iustin Pop
        child_result = child.ComputeNodeTree(node)
518 a8083063 Iustin Pop
        if len(child_result) == 1:
519 a8083063 Iustin Pop
          # child (and all its descendants) is simple, doesn't split
520 a8083063 Iustin Pop
          # over multiple hosts, so we don't need to describe it, our
521 a8083063 Iustin Pop
          # own entry for this node describes it completely
522 a8083063 Iustin Pop
          continue
523 a8083063 Iustin Pop
        else:
524 a8083063 Iustin Pop
          # check if child nodes differ from my nodes; note that
525 a8083063 Iustin Pop
          # subdisk can differ from the child itself, and be instead
526 a8083063 Iustin Pop
          # one of its descendants
527 a8083063 Iustin Pop
          for subnode, subdisk in child_result:
528 a8083063 Iustin Pop
            if subnode not in my_nodes:
529 a8083063 Iustin Pop
              result.append((subnode, subdisk))
530 a8083063 Iustin Pop
            # otherwise child is under our own node, so we ignore this
531 a8083063 Iustin Pop
            # entry (but probably the other results in the list will
532 a8083063 Iustin Pop
            # be different)
533 a8083063 Iustin Pop
    return result
534 a8083063 Iustin Pop
535 6d33a6eb Iustin Pop
  def ComputeGrowth(self, amount):
536 6d33a6eb Iustin Pop
    """Compute the per-VG growth requirements.
537 6d33a6eb Iustin Pop

538 6d33a6eb Iustin Pop
    This only works for VG-based disks.
539 6d33a6eb Iustin Pop

540 6d33a6eb Iustin Pop
    @type amount: integer
541 6d33a6eb Iustin Pop
    @param amount: the desired increase in (user-visible) disk space
542 6d33a6eb Iustin Pop
    @rtype: dict
543 6d33a6eb Iustin Pop
    @return: a dictionary of volume-groups and the required size
544 6d33a6eb Iustin Pop

545 6d33a6eb Iustin Pop
    """
546 6d33a6eb Iustin Pop
    if self.dev_type == constants.LD_LV:
547 6d33a6eb Iustin Pop
      return {self.logical_id[0]: amount}
548 6d33a6eb Iustin Pop
    elif self.dev_type == constants.LD_DRBD8:
549 6d33a6eb Iustin Pop
      if self.children:
550 6d33a6eb Iustin Pop
        return self.children[0].ComputeGrowth(amount)
551 6d33a6eb Iustin Pop
      else:
552 6d33a6eb Iustin Pop
        return {}
553 6d33a6eb Iustin Pop
    else:
554 6d33a6eb Iustin Pop
      # Other disk types do not require VG space
555 6d33a6eb Iustin Pop
      return {}
556 6d33a6eb Iustin Pop
557 acec9d51 Iustin Pop
  def RecordGrow(self, amount):
558 acec9d51 Iustin Pop
    """Update the size of this disk after growth.
559 acec9d51 Iustin Pop

560 acec9d51 Iustin Pop
    This method recurses over the disks's children and updates their
561 acec9d51 Iustin Pop
    size correspondigly. The method needs to be kept in sync with the
562 acec9d51 Iustin Pop
    actual algorithms from bdev.
563 acec9d51 Iustin Pop

564 acec9d51 Iustin Pop
    """
565 4b97f902 Apollon Oikonomopoulos
    if self.dev_type in (constants.LD_LV, constants.LD_FILE):
566 acec9d51 Iustin Pop
      self.size += amount
567 acec9d51 Iustin Pop
    elif self.dev_type == constants.LD_DRBD8:
568 acec9d51 Iustin Pop
      if self.children:
569 acec9d51 Iustin Pop
        self.children[0].RecordGrow(amount)
570 acec9d51 Iustin Pop
      self.size += amount
571 acec9d51 Iustin Pop
    else:
572 acec9d51 Iustin Pop
      raise errors.ProgrammerError("Disk.RecordGrow called for unsupported"
573 acec9d51 Iustin Pop
                                   " disk type %s" % self.dev_type)
574 acec9d51 Iustin Pop
575 a805ec18 Iustin Pop
  def UnsetSize(self):
576 a805ec18 Iustin Pop
    """Sets recursively the size to zero for the disk and its children.
577 a805ec18 Iustin Pop

578 a805ec18 Iustin Pop
    """
579 a805ec18 Iustin Pop
    if self.children:
580 a805ec18 Iustin Pop
      for child in self.children:
581 a805ec18 Iustin Pop
        child.UnsetSize()
582 a805ec18 Iustin Pop
    self.size = 0
583 a805ec18 Iustin Pop
584 0402302c Iustin Pop
  def SetPhysicalID(self, target_node, nodes_ip):
585 0402302c Iustin Pop
    """Convert the logical ID to the physical ID.
586 0402302c Iustin Pop

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

589 0402302c Iustin Pop
    The routine descends down and updates its children also, because
590 0402302c Iustin Pop
    this helps when the only the top device is passed to the remote
591 0402302c Iustin Pop
    node.
592 0402302c Iustin Pop

593 0402302c Iustin Pop
    Arguments:
594 0402302c Iustin Pop
      - target_node: the node we wish to configure for
595 0402302c Iustin Pop
      - nodes_ip: a mapping of node name to ip
596 0402302c Iustin Pop

597 0402302c Iustin Pop
    The target_node must exist in in nodes_ip, and must be one of the
598 0402302c Iustin Pop
    nodes in the logical ID for each of the DRBD devices encountered
599 0402302c Iustin Pop
    in the disk tree.
600 0402302c Iustin Pop

601 0402302c Iustin Pop
    """
602 0402302c Iustin Pop
    if self.children:
603 0402302c Iustin Pop
      for child in self.children:
604 0402302c Iustin Pop
        child.SetPhysicalID(target_node, nodes_ip)
605 0402302c Iustin Pop
606 0402302c Iustin Pop
    if self.logical_id is None and self.physical_id is not None:
607 0402302c Iustin Pop
      return
608 0402302c Iustin Pop
    if self.dev_type in constants.LDS_DRBD:
609 f9518d38 Iustin Pop
      pnode, snode, port, pminor, sminor, secret = self.logical_id
610 0402302c Iustin Pop
      if target_node not in (pnode, snode):
611 0402302c Iustin Pop
        raise errors.ConfigurationError("DRBD device not knowing node %s" %
612 0402302c Iustin Pop
                                        target_node)
613 0402302c Iustin Pop
      pnode_ip = nodes_ip.get(pnode, None)
614 0402302c Iustin Pop
      snode_ip = nodes_ip.get(snode, None)
615 0402302c Iustin Pop
      if pnode_ip is None or snode_ip is None:
616 0402302c Iustin Pop
        raise errors.ConfigurationError("Can't find primary or secondary node"
617 0402302c Iustin Pop
                                        " for %s" % str(self))
618 ffa1c0dc Iustin Pop
      p_data = (pnode_ip, port)
619 ffa1c0dc Iustin Pop
      s_data = (snode_ip, port)
620 0402302c Iustin Pop
      if pnode == target_node:
621 f9518d38 Iustin Pop
        self.physical_id = p_data + s_data + (pminor, secret)
622 0402302c Iustin Pop
      else: # it must be secondary, we tested above
623 f9518d38 Iustin Pop
        self.physical_id = s_data + p_data + (sminor, secret)
624 0402302c Iustin Pop
    else:
625 0402302c Iustin Pop
      self.physical_id = self.logical_id
626 0402302c Iustin Pop
    return
627 0402302c Iustin Pop
628 ff9c047c Iustin Pop
  def ToDict(self):
629 ff9c047c Iustin Pop
    """Disk-specific conversion to standard python types.
630 ff9c047c Iustin Pop

631 ff9c047c Iustin Pop
    This replaces the children lists of objects with lists of
632 ff9c047c Iustin Pop
    standard python types.
633 ff9c047c Iustin Pop

634 ff9c047c Iustin Pop
    """
635 ff9c047c Iustin Pop
    bo = super(Disk, self).ToDict()
636 ff9c047c Iustin Pop
637 ff9c047c Iustin Pop
    for attr in ("children",):
638 ff9c047c Iustin Pop
      alist = bo.get(attr, None)
639 ff9c047c Iustin Pop
      if alist:
640 ff9c047c Iustin Pop
        bo[attr] = self._ContainerToDicts(alist)
641 ff9c047c Iustin Pop
    return bo
642 ff9c047c Iustin Pop
643 ff9c047c Iustin Pop
  @classmethod
644 ff9c047c Iustin Pop
  def FromDict(cls, val):
645 ff9c047c Iustin Pop
    """Custom function for Disks
646 ff9c047c Iustin Pop

647 ff9c047c Iustin Pop
    """
648 ff9c047c Iustin Pop
    obj = super(Disk, cls).FromDict(val)
649 ff9c047c Iustin Pop
    if obj.children:
650 ff9c047c Iustin Pop
      obj.children = cls._ContainerFromDicts(obj.children, list, Disk)
651 ff9c047c Iustin Pop
    if obj.logical_id and isinstance(obj.logical_id, list):
652 ff9c047c Iustin Pop
      obj.logical_id = tuple(obj.logical_id)
653 ff9c047c Iustin Pop
    if obj.physical_id and isinstance(obj.physical_id, list):
654 ff9c047c Iustin Pop
      obj.physical_id = tuple(obj.physical_id)
655 f9518d38 Iustin Pop
    if obj.dev_type in constants.LDS_DRBD:
656 f9518d38 Iustin Pop
      # we need a tuple of length six here
657 f9518d38 Iustin Pop
      if len(obj.logical_id) < 6:
658 f9518d38 Iustin Pop
        obj.logical_id += (None,) * (6 - len(obj.logical_id))
659 ff9c047c Iustin Pop
    return obj
660 ff9c047c Iustin Pop
661 65a15336 Iustin Pop
  def __str__(self):
662 65a15336 Iustin Pop
    """Custom str() formatter for disks.
663 65a15336 Iustin Pop

664 65a15336 Iustin Pop
    """
665 65a15336 Iustin Pop
    if self.dev_type == constants.LD_LV:
666 e687ec01 Michael Hanselmann
      val = "<LogicalVolume(/dev/%s/%s" % self.logical_id
667 65a15336 Iustin Pop
    elif self.dev_type in constants.LDS_DRBD:
668 89f28b76 Iustin Pop
      node_a, node_b, port, minor_a, minor_b = self.logical_id[:5]
669 00fb8246 Michael Hanselmann
      val = "<DRBD8("
670 073ca59e Iustin Pop
      if self.physical_id is None:
671 073ca59e Iustin Pop
        phy = "unconfigured"
672 073ca59e Iustin Pop
      else:
673 073ca59e Iustin Pop
        phy = ("configured as %s:%s %s:%s" %
674 25a915d0 Iustin Pop
               (self.physical_id[0], self.physical_id[1],
675 25a915d0 Iustin Pop
                self.physical_id[2], self.physical_id[3]))
676 073ca59e Iustin Pop
677 89f28b76 Iustin Pop
      val += ("hosts=%s/%d-%s/%d, port=%s, %s, " %
678 89f28b76 Iustin Pop
              (node_a, minor_a, node_b, minor_b, port, phy))
679 65a15336 Iustin Pop
      if self.children and self.children.count(None) == 0:
680 65a15336 Iustin Pop
        val += "backend=%s, metadev=%s" % (self.children[0], self.children[1])
681 65a15336 Iustin Pop
      else:
682 65a15336 Iustin Pop
        val += "no local storage"
683 65a15336 Iustin Pop
    else:
684 65a15336 Iustin Pop
      val = ("<Disk(type=%s, logical_id=%s, physical_id=%s, children=%s" %
685 65a15336 Iustin Pop
             (self.dev_type, self.logical_id, self.physical_id, self.children))
686 65a15336 Iustin Pop
    if self.iv_name is None:
687 65a15336 Iustin Pop
      val += ", not visible"
688 65a15336 Iustin Pop
    else:
689 65a15336 Iustin Pop
      val += ", visible as /dev/%s" % self.iv_name
690 fd965830 Iustin Pop
    if isinstance(self.size, int):
691 fd965830 Iustin Pop
      val += ", size=%dm)>" % self.size
692 fd965830 Iustin Pop
    else:
693 fd965830 Iustin Pop
      val += ", size='%s')>" % (self.size,)
694 65a15336 Iustin Pop
    return val
695 65a15336 Iustin Pop
696 332d0e37 Iustin Pop
  def Verify(self):
697 332d0e37 Iustin Pop
    """Checks that this disk is correctly configured.
698 332d0e37 Iustin Pop

699 332d0e37 Iustin Pop
    """
700 7c4d6c7b Michael Hanselmann
    all_errors = []
701 332d0e37 Iustin Pop
    if self.mode not in constants.DISK_ACCESS_SET:
702 7c4d6c7b Michael Hanselmann
      all_errors.append("Disk access mode '%s' is invalid" % (self.mode, ))
703 7c4d6c7b Michael Hanselmann
    return all_errors
704 332d0e37 Iustin Pop
705 90d726a8 Iustin Pop
  def UpgradeConfig(self):
706 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
707 90d726a8 Iustin Pop

708 90d726a8 Iustin Pop
    """
709 90d726a8 Iustin Pop
    if self.children:
710 90d726a8 Iustin Pop
      for child in self.children:
711 90d726a8 Iustin Pop
        child.UpgradeConfig()
712 90d726a8 Iustin Pop
    # add here config upgrade for this disk
713 90d726a8 Iustin Pop
714 a8083063 Iustin Pop
715 ec29fe40 Iustin Pop
class Instance(TaggableObject):
716 a8083063 Iustin Pop
  """Config object representing an instance."""
717 154b9580 Balazs Lecz
  __slots__ = [
718 a8083063 Iustin Pop
    "name",
719 a8083063 Iustin Pop
    "primary_node",
720 a8083063 Iustin Pop
    "os",
721 e69d05fd Iustin Pop
    "hypervisor",
722 5bf7b5cf Iustin Pop
    "hvparams",
723 5bf7b5cf Iustin Pop
    "beparams",
724 1bdcbbab Iustin Pop
    "osparams",
725 0d68c45d Iustin Pop
    "admin_up",
726 a8083063 Iustin Pop
    "nics",
727 a8083063 Iustin Pop
    "disks",
728 a8083063 Iustin Pop
    "disk_template",
729 58acb49d Alexander Schreiber
    "network_port",
730 be1fa613 Iustin Pop
    "serial_no",
731 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
732 a8083063 Iustin Pop
733 a8083063 Iustin Pop
  def _ComputeSecondaryNodes(self):
734 a8083063 Iustin Pop
    """Compute the list of secondary nodes.
735 a8083063 Iustin Pop

736 cfcc5c6d Iustin Pop
    This is a simple wrapper over _ComputeAllNodes.
737 cfcc5c6d Iustin Pop

738 cfcc5c6d Iustin Pop
    """
739 cfcc5c6d Iustin Pop
    all_nodes = set(self._ComputeAllNodes())
740 cfcc5c6d Iustin Pop
    all_nodes.discard(self.primary_node)
741 cfcc5c6d Iustin Pop
    return tuple(all_nodes)
742 cfcc5c6d Iustin Pop
743 cfcc5c6d Iustin Pop
  secondary_nodes = property(_ComputeSecondaryNodes, None, None,
744 cfcc5c6d Iustin Pop
                             "List of secondary nodes")
745 cfcc5c6d Iustin Pop
746 cfcc5c6d Iustin Pop
  def _ComputeAllNodes(self):
747 cfcc5c6d Iustin Pop
    """Compute the list of all nodes.
748 cfcc5c6d Iustin Pop

749 a8083063 Iustin Pop
    Since the data is already there (in the drbd disks), keeping it as
750 a8083063 Iustin Pop
    a separate normal attribute is redundant and if not properly
751 a8083063 Iustin Pop
    synchronised can cause problems. Thus it's better to compute it
752 a8083063 Iustin Pop
    dynamically.
753 a8083063 Iustin Pop

754 a8083063 Iustin Pop
    """
755 cfcc5c6d Iustin Pop
    def _Helper(nodes, device):
756 cfcc5c6d Iustin Pop
      """Recursively computes nodes given a top device."""
757 a1f445d3 Iustin Pop
      if device.dev_type in constants.LDS_DRBD:
758 cfcc5c6d Iustin Pop
        nodea, nodeb = device.logical_id[:2]
759 cfcc5c6d Iustin Pop
        nodes.add(nodea)
760 cfcc5c6d Iustin Pop
        nodes.add(nodeb)
761 a8083063 Iustin Pop
      if device.children:
762 a8083063 Iustin Pop
        for child in device.children:
763 cfcc5c6d Iustin Pop
          _Helper(nodes, child)
764 a8083063 Iustin Pop
765 cfcc5c6d Iustin Pop
    all_nodes = set()
766 99c7b2a1 Iustin Pop
    all_nodes.add(self.primary_node)
767 a8083063 Iustin Pop
    for device in self.disks:
768 cfcc5c6d Iustin Pop
      _Helper(all_nodes, device)
769 cfcc5c6d Iustin Pop
    return tuple(all_nodes)
770 a8083063 Iustin Pop
771 cfcc5c6d Iustin Pop
  all_nodes = property(_ComputeAllNodes, None, None,
772 cfcc5c6d Iustin Pop
                       "List of all nodes of the instance")
773 a8083063 Iustin Pop
774 a8083063 Iustin Pop
  def MapLVsByNode(self, lvmap=None, devs=None, node=None):
775 a8083063 Iustin Pop
    """Provide a mapping of nodes to LVs this instance owns.
776 a8083063 Iustin Pop

777 c41eea6e Iustin Pop
    This function figures out what logical volumes should belong on
778 c41eea6e Iustin Pop
    which nodes, recursing through a device tree.
779 a8083063 Iustin Pop

780 c41eea6e Iustin Pop
    @param lvmap: optional dictionary to receive the
781 c41eea6e Iustin Pop
        'node' : ['lv', ...] data.
782 a8083063 Iustin Pop

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

788 a8083063 Iustin Pop
    """
789 a8083063 Iustin Pop
    if node == None:
790 a8083063 Iustin Pop
      node = self.primary_node
791 a8083063 Iustin Pop
792 a8083063 Iustin Pop
    if lvmap is None:
793 e687ec01 Michael Hanselmann
      lvmap = {
794 e687ec01 Michael Hanselmann
        node: [],
795 e687ec01 Michael Hanselmann
        }
796 a8083063 Iustin Pop
      ret = lvmap
797 a8083063 Iustin Pop
    else:
798 a8083063 Iustin Pop
      if not node in lvmap:
799 a8083063 Iustin Pop
        lvmap[node] = []
800 a8083063 Iustin Pop
      ret = None
801 a8083063 Iustin Pop
802 a8083063 Iustin Pop
    if not devs:
803 a8083063 Iustin Pop
      devs = self.disks
804 a8083063 Iustin Pop
805 a8083063 Iustin Pop
    for dev in devs:
806 fe96220b Iustin Pop
      if dev.dev_type == constants.LD_LV:
807 e687ec01 Michael Hanselmann
        lvmap[node].append(dev.logical_id[0] + "/" + dev.logical_id[1])
808 a8083063 Iustin Pop
809 a1f445d3 Iustin Pop
      elif dev.dev_type in constants.LDS_DRBD:
810 a8083063 Iustin Pop
        if dev.children:
811 a8083063 Iustin Pop
          self.MapLVsByNode(lvmap, dev.children, dev.logical_id[0])
812 a8083063 Iustin Pop
          self.MapLVsByNode(lvmap, dev.children, dev.logical_id[1])
813 a8083063 Iustin Pop
814 a8083063 Iustin Pop
      elif dev.children:
815 a8083063 Iustin Pop
        self.MapLVsByNode(lvmap, dev.children, node)
816 a8083063 Iustin Pop
817 a8083063 Iustin Pop
    return ret
818 a8083063 Iustin Pop
819 ad24e046 Iustin Pop
  def FindDisk(self, idx):
820 ad24e046 Iustin Pop
    """Find a disk given having a specified index.
821 644eeef9 Iustin Pop

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

824 ad24e046 Iustin Pop
    @type idx: int
825 ad24e046 Iustin Pop
    @param idx: the disk index
826 ad24e046 Iustin Pop
    @rtype: L{Disk}
827 ad24e046 Iustin Pop
    @return: the corresponding disk
828 ad24e046 Iustin Pop
    @raise errors.OpPrereqError: when the given index is not valid
829 644eeef9 Iustin Pop

830 ad24e046 Iustin Pop
    """
831 ad24e046 Iustin Pop
    try:
832 ad24e046 Iustin Pop
      idx = int(idx)
833 ad24e046 Iustin Pop
      return self.disks[idx]
834 691744c4 Iustin Pop
    except (TypeError, ValueError), err:
835 debac808 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index: '%s'" % str(err),
836 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
837 ad24e046 Iustin Pop
    except IndexError:
838 ad24e046 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index: %d (instace has disks"
839 daa55b04 Michael Hanselmann
                                 " 0 to %d" % (idx, len(self.disks) - 1),
840 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
841 644eeef9 Iustin Pop
842 ff9c047c Iustin Pop
  def ToDict(self):
843 ff9c047c Iustin Pop
    """Instance-specific conversion to standard python types.
844 ff9c047c Iustin Pop

845 ff9c047c Iustin Pop
    This replaces the children lists of objects with lists of standard
846 ff9c047c Iustin Pop
    python types.
847 ff9c047c Iustin Pop

848 ff9c047c Iustin Pop
    """
849 ff9c047c Iustin Pop
    bo = super(Instance, self).ToDict()
850 ff9c047c Iustin Pop
851 ff9c047c Iustin Pop
    for attr in "nics", "disks":
852 ff9c047c Iustin Pop
      alist = bo.get(attr, None)
853 ff9c047c Iustin Pop
      if alist:
854 ff9c047c Iustin Pop
        nlist = self._ContainerToDicts(alist)
855 ff9c047c Iustin Pop
      else:
856 ff9c047c Iustin Pop
        nlist = []
857 ff9c047c Iustin Pop
      bo[attr] = nlist
858 ff9c047c Iustin Pop
    return bo
859 ff9c047c Iustin Pop
860 ff9c047c Iustin Pop
  @classmethod
861 ff9c047c Iustin Pop
  def FromDict(cls, val):
862 ff9c047c Iustin Pop
    """Custom function for instances.
863 ff9c047c Iustin Pop

864 ff9c047c Iustin Pop
    """
865 ff9c047c Iustin Pop
    obj = super(Instance, cls).FromDict(val)
866 ff9c047c Iustin Pop
    obj.nics = cls._ContainerFromDicts(obj.nics, list, NIC)
867 ff9c047c Iustin Pop
    obj.disks = cls._ContainerFromDicts(obj.disks, list, Disk)
868 ff9c047c Iustin Pop
    return obj
869 ff9c047c Iustin Pop
870 90d726a8 Iustin Pop
  def UpgradeConfig(self):
871 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
872 90d726a8 Iustin Pop

873 90d726a8 Iustin Pop
    """
874 90d726a8 Iustin Pop
    for nic in self.nics:
875 90d726a8 Iustin Pop
      nic.UpgradeConfig()
876 90d726a8 Iustin Pop
    for disk in self.disks:
877 90d726a8 Iustin Pop
      disk.UpgradeConfig()
878 7736a5f2 Iustin Pop
    if self.hvparams:
879 7736a5f2 Iustin Pop
      for key in constants.HVC_GLOBALS:
880 7736a5f2 Iustin Pop
        try:
881 7736a5f2 Iustin Pop
          del self.hvparams[key]
882 7736a5f2 Iustin Pop
        except KeyError:
883 7736a5f2 Iustin Pop
          pass
884 1bdcbbab Iustin Pop
    if self.osparams is None:
885 1bdcbbab Iustin Pop
      self.osparams = {}
886 90d726a8 Iustin Pop
887 a8083063 Iustin Pop
888 a8083063 Iustin Pop
class OS(ConfigObject):
889 b41b3516 Iustin Pop
  """Config object representing an operating system.
890 b41b3516 Iustin Pop

891 b41b3516 Iustin Pop
  @type supported_parameters: list
892 b41b3516 Iustin Pop
  @ivar supported_parameters: a list of tuples, name and description,
893 b41b3516 Iustin Pop
      containing the supported parameters by this OS
894 b41b3516 Iustin Pop

895 870dc44c Iustin Pop
  @type VARIANT_DELIM: string
896 870dc44c Iustin Pop
  @cvar VARIANT_DELIM: the variant delimiter
897 870dc44c Iustin Pop

898 b41b3516 Iustin Pop
  """
899 a8083063 Iustin Pop
  __slots__ = [
900 a8083063 Iustin Pop
    "name",
901 a8083063 Iustin Pop
    "path",
902 082a7f91 Guido Trotter
    "api_versions",
903 a8083063 Iustin Pop
    "create_script",
904 a8083063 Iustin Pop
    "export_script",
905 386b57af Iustin Pop
    "import_script",
906 386b57af Iustin Pop
    "rename_script",
907 b41b3516 Iustin Pop
    "verify_script",
908 6d79896b Guido Trotter
    "supported_variants",
909 b41b3516 Iustin Pop
    "supported_parameters",
910 a8083063 Iustin Pop
    ]
911 a8083063 Iustin Pop
912 870dc44c Iustin Pop
  VARIANT_DELIM = "+"
913 870dc44c Iustin Pop
914 870dc44c Iustin Pop
  @classmethod
915 870dc44c Iustin Pop
  def SplitNameVariant(cls, name):
916 870dc44c Iustin Pop
    """Splits the name into the proper name and variant.
917 870dc44c Iustin Pop

918 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
919 870dc44c Iustin Pop
    @rtype: list
920 870dc44c Iustin Pop
    @return: a list of two elements; if the original name didn't
921 870dc44c Iustin Pop
        contain a variant, it's returned as an empty string
922 870dc44c Iustin Pop

923 870dc44c Iustin Pop
    """
924 870dc44c Iustin Pop
    nv = name.split(cls.VARIANT_DELIM, 1)
925 870dc44c Iustin Pop
    if len(nv) == 1:
926 870dc44c Iustin Pop
      nv.append("")
927 870dc44c Iustin Pop
    return nv
928 870dc44c Iustin Pop
929 870dc44c Iustin Pop
  @classmethod
930 870dc44c Iustin Pop
  def GetName(cls, name):
931 870dc44c Iustin Pop
    """Returns the proper name of the os (without the variant).
932 870dc44c Iustin Pop

933 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
934 870dc44c Iustin Pop

935 870dc44c Iustin Pop
    """
936 870dc44c Iustin Pop
    return cls.SplitNameVariant(name)[0]
937 870dc44c Iustin Pop
938 870dc44c Iustin Pop
  @classmethod
939 870dc44c Iustin Pop
  def GetVariant(cls, name):
940 870dc44c Iustin Pop
    """Returns the variant the os (without the base name).
941 870dc44c Iustin Pop

942 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
943 870dc44c Iustin Pop

944 870dc44c Iustin Pop
    """
945 870dc44c Iustin Pop
    return cls.SplitNameVariant(name)[1]
946 870dc44c Iustin Pop
947 7c0d6283 Michael Hanselmann
948 ec29fe40 Iustin Pop
class Node(TaggableObject):
949 a8083063 Iustin Pop
  """Config object representing a node."""
950 154b9580 Balazs Lecz
  __slots__ = [
951 ec29fe40 Iustin Pop
    "name",
952 ec29fe40 Iustin Pop
    "primary_ip",
953 ec29fe40 Iustin Pop
    "secondary_ip",
954 be1fa613 Iustin Pop
    "serial_no",
955 8b8b8b81 Iustin Pop
    "master_candidate",
956 fc0fe88c Iustin Pop
    "offline",
957 af64c0ea Iustin Pop
    "drained",
958 f936c153 Iustin Pop
    "group",
959 490acd18 Iustin Pop
    "master_capable",
960 490acd18 Iustin Pop
    "vm_capable",
961 095e71aa Renรฉ Nussbaumer
    "ndparams",
962 25124d4a Renรฉ Nussbaumer
    "powered",
963 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
964 a8083063 Iustin Pop
965 490acd18 Iustin Pop
  def UpgradeConfig(self):
966 490acd18 Iustin Pop
    """Fill defaults for missing configuration values.
967 490acd18 Iustin Pop

968 490acd18 Iustin Pop
    """
969 b459a848 Andrea Spadaccini
    # pylint: disable=E0203
970 490acd18 Iustin Pop
    # because these are "defined" via slots, not manually
971 490acd18 Iustin Pop
    if self.master_capable is None:
972 490acd18 Iustin Pop
      self.master_capable = True
973 490acd18 Iustin Pop
974 490acd18 Iustin Pop
    if self.vm_capable is None:
975 490acd18 Iustin Pop
      self.vm_capable = True
976 490acd18 Iustin Pop
977 095e71aa Renรฉ Nussbaumer
    if self.ndparams is None:
978 095e71aa Renรฉ Nussbaumer
      self.ndparams = {}
979 095e71aa Renรฉ Nussbaumer
980 25124d4a Renรฉ Nussbaumer
    if self.powered is None:
981 25124d4a Renรฉ Nussbaumer
      self.powered = True
982 25124d4a Renรฉ Nussbaumer
983 a8083063 Iustin Pop
984 1ffd2673 Michael Hanselmann
class NodeGroup(TaggableObject):
985 24a3707f Guido Trotter
  """Config object representing a node group."""
986 24a3707f Guido Trotter
  __slots__ = [
987 24a3707f Guido Trotter
    "name",
988 24a3707f Guido Trotter
    "members",
989 095e71aa Renรฉ Nussbaumer
    "ndparams",
990 e11a1b77 Adeodato Simo
    "serial_no",
991 90e99856 Adeodato Simo
    "alloc_policy",
992 24a3707f Guido Trotter
    ] + _TIMESTAMPS + _UUID
993 24a3707f Guido Trotter
994 24a3707f Guido Trotter
  def ToDict(self):
995 24a3707f Guido Trotter
    """Custom function for nodegroup.
996 24a3707f Guido Trotter

997 c60abd62 Guido Trotter
    This discards the members object, which gets recalculated and is only kept
998 c60abd62 Guido Trotter
    in memory.
999 24a3707f Guido Trotter

1000 24a3707f Guido Trotter
    """
1001 24a3707f Guido Trotter
    mydict = super(NodeGroup, self).ToDict()
1002 24a3707f Guido Trotter
    del mydict["members"]
1003 24a3707f Guido Trotter
    return mydict
1004 24a3707f Guido Trotter
1005 24a3707f Guido Trotter
  @classmethod
1006 24a3707f Guido Trotter
  def FromDict(cls, val):
1007 24a3707f Guido Trotter
    """Custom function for nodegroup.
1008 24a3707f Guido Trotter

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

1011 24a3707f Guido Trotter
    """
1012 24a3707f Guido Trotter
    obj = super(NodeGroup, cls).FromDict(val)
1013 24a3707f Guido Trotter
    obj.members = []
1014 24a3707f Guido Trotter
    return obj
1015 24a3707f Guido Trotter
1016 095e71aa Renรฉ Nussbaumer
  def UpgradeConfig(self):
1017 095e71aa Renรฉ Nussbaumer
    """Fill defaults for missing configuration values.
1018 095e71aa Renรฉ Nussbaumer

1019 095e71aa Renรฉ Nussbaumer
    """
1020 095e71aa Renรฉ Nussbaumer
    if self.ndparams is None:
1021 095e71aa Renรฉ Nussbaumer
      self.ndparams = {}
1022 095e71aa Renรฉ Nussbaumer
1023 e11a1b77 Adeodato Simo
    if self.serial_no is None:
1024 e11a1b77 Adeodato Simo
      self.serial_no = 1
1025 e11a1b77 Adeodato Simo
1026 90e99856 Adeodato Simo
    if self.alloc_policy is None:
1027 90e99856 Adeodato Simo
      self.alloc_policy = constants.ALLOC_POLICY_PREFERRED
1028 90e99856 Adeodato Simo
1029 e11a1b77 Adeodato Simo
    # We only update mtime, and not ctime, since we would not be able to provide
1030 e11a1b77 Adeodato Simo
    # a correct value for creation time.
1031 e11a1b77 Adeodato Simo
    if self.mtime is None:
1032 e11a1b77 Adeodato Simo
      self.mtime = time.time()
1033 e11a1b77 Adeodato Simo
1034 095e71aa Renรฉ Nussbaumer
  def FillND(self, node):
1035 ce523de1 Michael Hanselmann
    """Return filled out ndparams for L{objects.Node}
1036 095e71aa Renรฉ Nussbaumer

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

1041 095e71aa Renรฉ Nussbaumer
    """
1042 095e71aa Renรฉ Nussbaumer
    return self.SimpleFillND(node.ndparams)
1043 095e71aa Renรฉ Nussbaumer
1044 095e71aa Renรฉ Nussbaumer
  def SimpleFillND(self, ndparams):
1045 095e71aa Renรฉ Nussbaumer
    """Fill a given ndparams dict with defaults.
1046 095e71aa Renรฉ Nussbaumer

1047 095e71aa Renรฉ Nussbaumer
    @type ndparams: dict
1048 095e71aa Renรฉ Nussbaumer
    @param ndparams: the dict to fill
1049 095e71aa Renรฉ Nussbaumer
    @rtype: dict
1050 095e71aa Renรฉ Nussbaumer
    @return: a copy of the passed in ndparams with missing keys filled
1051 e6e88de6 Adeodato Simo
        from the node group defaults
1052 095e71aa Renรฉ Nussbaumer

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

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

1183 319856a9 Michael Hanselmann
    """
1184 b60ae2ca Iustin Pop
    mydict = super(Cluster, self).ToDict()
1185 319856a9 Michael Hanselmann
    mydict["tcpudp_port_pool"] = list(self.tcpudp_port_pool)
1186 319856a9 Michael Hanselmann
    return mydict
1187 319856a9 Michael Hanselmann
1188 319856a9 Michael Hanselmann
  @classmethod
1189 319856a9 Michael Hanselmann
  def FromDict(cls, val):
1190 319856a9 Michael Hanselmann
    """Custom function for cluster.
1191 319856a9 Michael Hanselmann

1192 319856a9 Michael Hanselmann
    """
1193 b60ae2ca Iustin Pop
    obj = super(Cluster, cls).FromDict(val)
1194 319856a9 Michael Hanselmann
    if not isinstance(obj.tcpudp_port_pool, set):
1195 319856a9 Michael Hanselmann
      obj.tcpudp_port_pool = set(obj.tcpudp_port_pool)
1196 319856a9 Michael Hanselmann
    return obj
1197 319856a9 Michael Hanselmann
1198 d63479b5 Iustin Pop
  def GetHVDefaults(self, hypervisor, os_name=None, skip_keys=None):
1199 d63479b5 Iustin Pop
    """Get the default hypervisor parameters for the cluster.
1200 d63479b5 Iustin Pop

1201 d63479b5 Iustin Pop
    @param hypervisor: the hypervisor name
1202 d63479b5 Iustin Pop
    @param os_name: if specified, we'll also update the defaults for this OS
1203 d63479b5 Iustin Pop
    @param skip_keys: if passed, list of keys not to use
1204 d63479b5 Iustin Pop
    @return: the defaults dict
1205 d63479b5 Iustin Pop

1206 d63479b5 Iustin Pop
    """
1207 d63479b5 Iustin Pop
    if skip_keys is None:
1208 d63479b5 Iustin Pop
      skip_keys = []
1209 d63479b5 Iustin Pop
1210 d63479b5 Iustin Pop
    fill_stack = [self.hvparams.get(hypervisor, {})]
1211 d63479b5 Iustin Pop
    if os_name is not None:
1212 d63479b5 Iustin Pop
      os_hvp = self.os_hvp.get(os_name, {}).get(hypervisor, {})
1213 d63479b5 Iustin Pop
      fill_stack.append(os_hvp)
1214 d63479b5 Iustin Pop
1215 d63479b5 Iustin Pop
    ret_dict = {}
1216 d63479b5 Iustin Pop
    for o_dict in fill_stack:
1217 d63479b5 Iustin Pop
      ret_dict = FillDict(ret_dict, o_dict, skip_keys=skip_keys)
1218 d63479b5 Iustin Pop
1219 d63479b5 Iustin Pop
    return ret_dict
1220 d63479b5 Iustin Pop
1221 73e0328b Iustin Pop
  def SimpleFillHV(self, hv_name, os_name, hvparams, skip_globals=False):
1222 73e0328b Iustin Pop
    """Fill a given hvparams dict with cluster defaults.
1223 73e0328b Iustin Pop

1224 73e0328b Iustin Pop
    @type hv_name: string
1225 73e0328b Iustin Pop
    @param hv_name: the hypervisor to use
1226 73e0328b Iustin Pop
    @type os_name: string
1227 73e0328b Iustin Pop
    @param os_name: the OS to use for overriding the hypervisor defaults
1228 73e0328b Iustin Pop
    @type skip_globals: boolean
1229 73e0328b Iustin Pop
    @param skip_globals: if True, the global hypervisor parameters will
1230 73e0328b Iustin Pop
        not be filled
1231 73e0328b Iustin Pop
    @rtype: dict
1232 73e0328b Iustin Pop
    @return: a copy of the given hvparams with missing keys filled from
1233 73e0328b Iustin Pop
        the cluster defaults
1234 73e0328b Iustin Pop

1235 73e0328b Iustin Pop
    """
1236 73e0328b Iustin Pop
    if skip_globals:
1237 73e0328b Iustin Pop
      skip_keys = constants.HVC_GLOBALS
1238 73e0328b Iustin Pop
    else:
1239 73e0328b Iustin Pop
      skip_keys = []
1240 73e0328b Iustin Pop
1241 73e0328b Iustin Pop
    def_dict = self.GetHVDefaults(hv_name, os_name, skip_keys=skip_keys)
1242 73e0328b Iustin Pop
    return FillDict(def_dict, hvparams, skip_keys=skip_keys)
1243 d63479b5 Iustin Pop
1244 7736a5f2 Iustin Pop
  def FillHV(self, instance, skip_globals=False):
1245 73e0328b Iustin Pop
    """Fill an instance's hvparams dict with cluster defaults.
1246 5bf7b5cf Iustin Pop

1247 a2a24f4c Guido Trotter
    @type instance: L{objects.Instance}
1248 5bf7b5cf Iustin Pop
    @param instance: the instance parameter to fill
1249 7736a5f2 Iustin Pop
    @type skip_globals: boolean
1250 7736a5f2 Iustin Pop
    @param skip_globals: if True, the global hypervisor parameters will
1251 7736a5f2 Iustin Pop
        not be filled
1252 5bf7b5cf Iustin Pop
    @rtype: dict
1253 5bf7b5cf Iustin Pop
    @return: a copy of the instance's hvparams with missing keys filled from
1254 5bf7b5cf Iustin Pop
        the cluster defaults
1255 5bf7b5cf Iustin Pop

1256 5bf7b5cf Iustin Pop
    """
1257 73e0328b Iustin Pop
    return self.SimpleFillHV(instance.hypervisor, instance.os,
1258 73e0328b Iustin Pop
                             instance.hvparams, skip_globals)
1259 17463d22 Renรฉ Nussbaumer
1260 73e0328b Iustin Pop
  def SimpleFillBE(self, beparams):
1261 73e0328b Iustin Pop
    """Fill a given beparams dict with cluster defaults.
1262 73e0328b Iustin Pop

1263 06596a60 Guido Trotter
    @type beparams: dict
1264 06596a60 Guido Trotter
    @param beparams: the dict to fill
1265 73e0328b Iustin Pop
    @rtype: dict
1266 73e0328b Iustin Pop
    @return: a copy of the passed in beparams with missing keys filled
1267 73e0328b Iustin Pop
        from the cluster defaults
1268 73e0328b Iustin Pop

1269 73e0328b Iustin Pop
    """
1270 73e0328b Iustin Pop
    return FillDict(self.beparams.get(constants.PP_DEFAULT, {}), beparams)
1271 5bf7b5cf Iustin Pop
1272 5bf7b5cf Iustin Pop
  def FillBE(self, instance):
1273 73e0328b Iustin Pop
    """Fill an instance's beparams dict with cluster defaults.
1274 5bf7b5cf Iustin Pop

1275 a2a24f4c Guido Trotter
    @type instance: L{objects.Instance}
1276 5bf7b5cf Iustin Pop
    @param instance: the instance parameter to fill
1277 5bf7b5cf Iustin Pop
    @rtype: dict
1278 5bf7b5cf Iustin Pop
    @return: a copy of the instance's beparams with missing keys filled from
1279 5bf7b5cf Iustin Pop
        the cluster defaults
1280 5bf7b5cf Iustin Pop

1281 5bf7b5cf Iustin Pop
    """
1282 73e0328b Iustin Pop
    return self.SimpleFillBE(instance.beparams)
1283 73e0328b Iustin Pop
1284 73e0328b Iustin Pop
  def SimpleFillNIC(self, nicparams):
1285 73e0328b Iustin Pop
    """Fill a given nicparams dict with cluster defaults.
1286 73e0328b Iustin Pop

1287 06596a60 Guido Trotter
    @type nicparams: dict
1288 06596a60 Guido Trotter
    @param nicparams: the dict to fill
1289 73e0328b Iustin Pop
    @rtype: dict
1290 73e0328b Iustin Pop
    @return: a copy of the passed in nicparams with missing keys filled
1291 73e0328b Iustin Pop
        from the cluster defaults
1292 73e0328b Iustin Pop

1293 73e0328b Iustin Pop
    """
1294 73e0328b Iustin Pop
    return FillDict(self.nicparams.get(constants.PP_DEFAULT, {}), nicparams)
1295 5bf7b5cf Iustin Pop
1296 1bdcbbab Iustin Pop
  def SimpleFillOS(self, os_name, os_params):
1297 1bdcbbab Iustin Pop
    """Fill an instance's osparams dict with cluster defaults.
1298 1bdcbbab Iustin Pop

1299 1bdcbbab Iustin Pop
    @type os_name: string
1300 1bdcbbab Iustin Pop
    @param os_name: the OS name to use
1301 1bdcbbab Iustin Pop
    @type os_params: dict
1302 1bdcbbab Iustin Pop
    @param os_params: the dict to fill with default values
1303 1bdcbbab Iustin Pop
    @rtype: dict
1304 1bdcbbab Iustin Pop
    @return: a copy of the instance's osparams with missing keys filled from
1305 1bdcbbab Iustin Pop
        the cluster defaults
1306 1bdcbbab Iustin Pop

1307 1bdcbbab Iustin Pop
    """
1308 1bdcbbab Iustin Pop
    name_only = os_name.split("+", 1)[0]
1309 1bdcbbab Iustin Pop
    # base OS
1310 1bdcbbab Iustin Pop
    result = self.osparams.get(name_only, {})
1311 1bdcbbab Iustin Pop
    # OS with variant
1312 1bdcbbab Iustin Pop
    result = FillDict(result, self.osparams.get(os_name, {}))
1313 1bdcbbab Iustin Pop
    # specified params
1314 1bdcbbab Iustin Pop
    return FillDict(result, os_params)
1315 1bdcbbab Iustin Pop
1316 095e71aa Renรฉ Nussbaumer
  def FillND(self, node, nodegroup):
1317 ce523de1 Michael Hanselmann
    """Return filled out ndparams for L{objects.NodeGroup} and L{objects.Node}
1318 095e71aa Renรฉ Nussbaumer

1319 095e71aa Renรฉ Nussbaumer
    @type node: L{objects.Node}
1320 095e71aa Renรฉ Nussbaumer
    @param node: A Node object to fill
1321 095e71aa Renรฉ Nussbaumer
    @type nodegroup: L{objects.NodeGroup}
1322 095e71aa Renรฉ Nussbaumer
    @param nodegroup: A Node object to fill
1323 095e71aa Renรฉ Nussbaumer
    @return a copy of the node's ndparams with defaults filled
1324 095e71aa Renรฉ Nussbaumer

1325 095e71aa Renรฉ Nussbaumer
    """
1326 095e71aa Renรฉ Nussbaumer
    return self.SimpleFillND(nodegroup.FillND(node))
1327 095e71aa Renรฉ Nussbaumer
1328 095e71aa Renรฉ Nussbaumer
  def SimpleFillND(self, ndparams):
1329 095e71aa Renรฉ Nussbaumer
    """Fill a given ndparams dict with defaults.
1330 095e71aa Renรฉ Nussbaumer

1331 095e71aa Renรฉ Nussbaumer
    @type ndparams: dict
1332 095e71aa Renรฉ Nussbaumer
    @param ndparams: the dict to fill
1333 095e71aa Renรฉ Nussbaumer
    @rtype: dict
1334 095e71aa Renรฉ Nussbaumer
    @return: a copy of the passed in ndparams with missing keys filled
1335 095e71aa Renรฉ Nussbaumer
        from the cluster defaults
1336 095e71aa Renรฉ Nussbaumer

1337 095e71aa Renรฉ Nussbaumer
    """
1338 095e71aa Renรฉ Nussbaumer
    return FillDict(self.ndparams, ndparams)
1339 095e71aa Renรฉ Nussbaumer
1340 5c947f38 Iustin Pop
1341 96acbc09 Michael Hanselmann
class BlockDevStatus(ConfigObject):
1342 96acbc09 Michael Hanselmann
  """Config object representing the status of a block device."""
1343 96acbc09 Michael Hanselmann
  __slots__ = [
1344 96acbc09 Michael Hanselmann
    "dev_path",
1345 96acbc09 Michael Hanselmann
    "major",
1346 96acbc09 Michael Hanselmann
    "minor",
1347 96acbc09 Michael Hanselmann
    "sync_percent",
1348 96acbc09 Michael Hanselmann
    "estimated_time",
1349 96acbc09 Michael Hanselmann
    "is_degraded",
1350 f208978a Michael Hanselmann
    "ldisk_status",
1351 96acbc09 Michael Hanselmann
    ]
1352 96acbc09 Michael Hanselmann
1353 96acbc09 Michael Hanselmann
1354 2d76b580 Michael Hanselmann
class ImportExportStatus(ConfigObject):
1355 2d76b580 Michael Hanselmann
  """Config object representing the status of an import or export."""
1356 2d76b580 Michael Hanselmann
  __slots__ = [
1357 2d76b580 Michael Hanselmann
    "recent_output",
1358 2d76b580 Michael Hanselmann
    "listen_port",
1359 2d76b580 Michael Hanselmann
    "connected",
1360 c08d76f5 Michael Hanselmann
    "progress_mbytes",
1361 c08d76f5 Michael Hanselmann
    "progress_throughput",
1362 c08d76f5 Michael Hanselmann
    "progress_eta",
1363 c08d76f5 Michael Hanselmann
    "progress_percent",
1364 2d76b580 Michael Hanselmann
    "exit_status",
1365 2d76b580 Michael Hanselmann
    "error_message",
1366 2d76b580 Michael Hanselmann
    ] + _TIMESTAMPS
1367 2d76b580 Michael Hanselmann
1368 2d76b580 Michael Hanselmann
1369 eb630f50 Michael Hanselmann
class ImportExportOptions(ConfigObject):
1370 eb630f50 Michael Hanselmann
  """Options for import/export daemon
1371 eb630f50 Michael Hanselmann

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

1379 eb630f50 Michael Hanselmann
  """
1380 eb630f50 Michael Hanselmann
  __slots__ = [
1381 eb630f50 Michael Hanselmann
    "key_name",
1382 eb630f50 Michael Hanselmann
    "ca_pem",
1383 a5310c2a Michael Hanselmann
    "compress",
1384 af1d39b1 Michael Hanselmann
    "magic",
1385 855d2fc7 Michael Hanselmann
    "ipv6",
1386 4478301b Michael Hanselmann
    "connect_timeout",
1387 eb630f50 Michael Hanselmann
    ]
1388 eb630f50 Michael Hanselmann
1389 eb630f50 Michael Hanselmann
1390 18d750b9 Guido Trotter
class ConfdRequest(ConfigObject):
1391 18d750b9 Guido Trotter
  """Object holding a confd request.
1392 18d750b9 Guido Trotter

1393 18d750b9 Guido Trotter
  @ivar protocol: confd protocol version
1394 18d750b9 Guido Trotter
  @ivar type: confd query type
1395 18d750b9 Guido Trotter
  @ivar query: query request
1396 18d750b9 Guido Trotter
  @ivar rsalt: requested reply salt
1397 18d750b9 Guido Trotter

1398 18d750b9 Guido Trotter
  """
1399 18d750b9 Guido Trotter
  __slots__ = [
1400 18d750b9 Guido Trotter
    "protocol",
1401 18d750b9 Guido Trotter
    "type",
1402 18d750b9 Guido Trotter
    "query",
1403 18d750b9 Guido Trotter
    "rsalt",
1404 18d750b9 Guido Trotter
    ]
1405 18d750b9 Guido Trotter
1406 18d750b9 Guido Trotter
1407 18d750b9 Guido Trotter
class ConfdReply(ConfigObject):
1408 18d750b9 Guido Trotter
  """Object holding a confd reply.
1409 18d750b9 Guido Trotter

1410 18d750b9 Guido Trotter
  @ivar protocol: confd protocol version
1411 18d750b9 Guido Trotter
  @ivar status: reply status code (ok, error)
1412 18d750b9 Guido Trotter
  @ivar answer: confd query reply
1413 18d750b9 Guido Trotter
  @ivar serial: configuration serial number
1414 18d750b9 Guido Trotter

1415 18d750b9 Guido Trotter
  """
1416 18d750b9 Guido Trotter
  __slots__ = [
1417 18d750b9 Guido Trotter
    "protocol",
1418 18d750b9 Guido Trotter
    "status",
1419 18d750b9 Guido Trotter
    "answer",
1420 18d750b9 Guido Trotter
    "serial",
1421 18d750b9 Guido Trotter
    ]
1422 18d750b9 Guido Trotter
1423 18d750b9 Guido Trotter
1424 707f23b5 Michael Hanselmann
class QueryFieldDefinition(ConfigObject):
1425 707f23b5 Michael Hanselmann
  """Object holding a query field definition.
1426 707f23b5 Michael Hanselmann

1427 24d6d3e2 Michael Hanselmann
  @ivar name: Field name
1428 707f23b5 Michael Hanselmann
  @ivar title: Human-readable title
1429 707f23b5 Michael Hanselmann
  @ivar kind: Field type
1430 1ae17369 Michael Hanselmann
  @ivar doc: Human-readable description
1431 707f23b5 Michael Hanselmann

1432 707f23b5 Michael Hanselmann
  """
1433 707f23b5 Michael Hanselmann
  __slots__ = [
1434 707f23b5 Michael Hanselmann
    "name",
1435 707f23b5 Michael Hanselmann
    "title",
1436 707f23b5 Michael Hanselmann
    "kind",
1437 1ae17369 Michael Hanselmann
    "doc",
1438 707f23b5 Michael Hanselmann
    ]
1439 707f23b5 Michael Hanselmann
1440 707f23b5 Michael Hanselmann
1441 0538c375 Michael Hanselmann
class _QueryResponseBase(ConfigObject):
1442 0538c375 Michael Hanselmann
  __slots__ = [
1443 0538c375 Michael Hanselmann
    "fields",
1444 0538c375 Michael Hanselmann
    ]
1445 0538c375 Michael Hanselmann
1446 0538c375 Michael Hanselmann
  def ToDict(self):
1447 0538c375 Michael Hanselmann
    """Custom function for serializing.
1448 0538c375 Michael Hanselmann

1449 0538c375 Michael Hanselmann
    """
1450 0538c375 Michael Hanselmann
    mydict = super(_QueryResponseBase, self).ToDict()
1451 0538c375 Michael Hanselmann
    mydict["fields"] = self._ContainerToDicts(mydict["fields"])
1452 0538c375 Michael Hanselmann
    return mydict
1453 0538c375 Michael Hanselmann
1454 0538c375 Michael Hanselmann
  @classmethod
1455 0538c375 Michael Hanselmann
  def FromDict(cls, val):
1456 0538c375 Michael Hanselmann
    """Custom function for de-serializing.
1457 0538c375 Michael Hanselmann

1458 0538c375 Michael Hanselmann
    """
1459 0538c375 Michael Hanselmann
    obj = super(_QueryResponseBase, cls).FromDict(val)
1460 0538c375 Michael Hanselmann
    obj.fields = cls._ContainerFromDicts(obj.fields, list, QueryFieldDefinition)
1461 0538c375 Michael Hanselmann
    return obj
1462 0538c375 Michael Hanselmann
1463 0538c375 Michael Hanselmann
1464 24d6d3e2 Michael Hanselmann
class QueryRequest(ConfigObject):
1465 24d6d3e2 Michael Hanselmann
  """Object holding a query request.
1466 24d6d3e2 Michael Hanselmann

1467 24d6d3e2 Michael Hanselmann
  """
1468 24d6d3e2 Michael Hanselmann
  __slots__ = [
1469 24d6d3e2 Michael Hanselmann
    "what",
1470 24d6d3e2 Michael Hanselmann
    "fields",
1471 2e5c33db Iustin Pop
    "qfilter",
1472 24d6d3e2 Michael Hanselmann
    ]
1473 24d6d3e2 Michael Hanselmann
1474 24d6d3e2 Michael Hanselmann
1475 0538c375 Michael Hanselmann
class QueryResponse(_QueryResponseBase):
1476 24d6d3e2 Michael Hanselmann
  """Object holding the response to a query.
1477 24d6d3e2 Michael Hanselmann

1478 24d6d3e2 Michael Hanselmann
  @ivar fields: List of L{QueryFieldDefinition} objects
1479 24d6d3e2 Michael Hanselmann
  @ivar data: Requested data
1480 24d6d3e2 Michael Hanselmann

1481 24d6d3e2 Michael Hanselmann
  """
1482 24d6d3e2 Michael Hanselmann
  __slots__ = [
1483 24d6d3e2 Michael Hanselmann
    "data",
1484 24d6d3e2 Michael Hanselmann
    ]
1485 24d6d3e2 Michael Hanselmann
1486 24d6d3e2 Michael Hanselmann
1487 24d6d3e2 Michael Hanselmann
class QueryFieldsRequest(ConfigObject):
1488 24d6d3e2 Michael Hanselmann
  """Object holding a request for querying available fields.
1489 24d6d3e2 Michael Hanselmann

1490 24d6d3e2 Michael Hanselmann
  """
1491 24d6d3e2 Michael Hanselmann
  __slots__ = [
1492 24d6d3e2 Michael Hanselmann
    "what",
1493 24d6d3e2 Michael Hanselmann
    "fields",
1494 24d6d3e2 Michael Hanselmann
    ]
1495 24d6d3e2 Michael Hanselmann
1496 24d6d3e2 Michael Hanselmann
1497 0538c375 Michael Hanselmann
class QueryFieldsResponse(_QueryResponseBase):
1498 24d6d3e2 Michael Hanselmann
  """Object holding the response to a query for fields.
1499 24d6d3e2 Michael Hanselmann

1500 24d6d3e2 Michael Hanselmann
  @ivar fields: List of L{QueryFieldDefinition} objects
1501 24d6d3e2 Michael Hanselmann

1502 24d6d3e2 Michael Hanselmann
  """
1503 24d6d3e2 Michael Hanselmann
  __slots__ = [
1504 24d6d3e2 Michael Hanselmann
    ]
1505 24d6d3e2 Michael Hanselmann
1506 24d6d3e2 Michael Hanselmann
1507 6a1434d7 Andrea Spadaccini
class MigrationStatus(ConfigObject):
1508 6a1434d7 Andrea Spadaccini
  """Object holding the status of a migration.
1509 6a1434d7 Andrea Spadaccini

1510 6a1434d7 Andrea Spadaccini
  """
1511 6a1434d7 Andrea Spadaccini
  __slots__ = [
1512 6a1434d7 Andrea Spadaccini
    "status",
1513 6a1434d7 Andrea Spadaccini
    "transferred_ram",
1514 6a1434d7 Andrea Spadaccini
    "total_ram",
1515 6a1434d7 Andrea Spadaccini
    ]
1516 6a1434d7 Andrea Spadaccini
1517 6a1434d7 Andrea Spadaccini
1518 25ce3ec4 Michael Hanselmann
class InstanceConsole(ConfigObject):
1519 25ce3ec4 Michael Hanselmann
  """Object describing how to access the console of an instance.
1520 25ce3ec4 Michael Hanselmann

1521 25ce3ec4 Michael Hanselmann
  """
1522 25ce3ec4 Michael Hanselmann
  __slots__ = [
1523 25ce3ec4 Michael Hanselmann
    "instance",
1524 25ce3ec4 Michael Hanselmann
    "kind",
1525 25ce3ec4 Michael Hanselmann
    "message",
1526 25ce3ec4 Michael Hanselmann
    "host",
1527 25ce3ec4 Michael Hanselmann
    "port",
1528 25ce3ec4 Michael Hanselmann
    "user",
1529 25ce3ec4 Michael Hanselmann
    "command",
1530 25ce3ec4 Michael Hanselmann
    "display",
1531 25ce3ec4 Michael Hanselmann
    ]
1532 25ce3ec4 Michael Hanselmann
1533 25ce3ec4 Michael Hanselmann
  def Validate(self):
1534 25ce3ec4 Michael Hanselmann
    """Validates contents of this object.
1535 25ce3ec4 Michael Hanselmann

1536 25ce3ec4 Michael Hanselmann
    """
1537 25ce3ec4 Michael Hanselmann
    assert self.kind in constants.CONS_ALL, "Unknown console type"
1538 25ce3ec4 Michael Hanselmann
    assert self.instance, "Missing instance name"
1539 4d2cdb5a Andrea Spadaccini
    assert self.message or self.kind in [constants.CONS_SSH,
1540 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1541 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_VNC]
1542 25ce3ec4 Michael Hanselmann
    assert self.host or self.kind == constants.CONS_MESSAGE
1543 25ce3ec4 Michael Hanselmann
    assert self.port or self.kind in [constants.CONS_MESSAGE,
1544 25ce3ec4 Michael Hanselmann
                                      constants.CONS_SSH]
1545 25ce3ec4 Michael Hanselmann
    assert self.user or self.kind in [constants.CONS_MESSAGE,
1546 4d2cdb5a Andrea Spadaccini
                                      constants.CONS_SPICE,
1547 25ce3ec4 Michael Hanselmann
                                      constants.CONS_VNC]
1548 25ce3ec4 Michael Hanselmann
    assert self.command or self.kind in [constants.CONS_MESSAGE,
1549 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1550 25ce3ec4 Michael Hanselmann
                                         constants.CONS_VNC]
1551 25ce3ec4 Michael Hanselmann
    assert self.display or self.kind in [constants.CONS_MESSAGE,
1552 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1553 25ce3ec4 Michael Hanselmann
                                         constants.CONS_SSH]
1554 25ce3ec4 Michael Hanselmann
    return True
1555 25ce3ec4 Michael Hanselmann
1556 25ce3ec4 Michael Hanselmann
1557 a8083063 Iustin Pop
class SerializableConfigParser(ConfigParser.SafeConfigParser):
1558 a8083063 Iustin Pop
  """Simple wrapper over ConfigParse that allows serialization.
1559 a8083063 Iustin Pop

1560 a8083063 Iustin Pop
  This class is basically ConfigParser.SafeConfigParser with two
1561 a8083063 Iustin Pop
  additional methods that allow it to serialize/unserialize to/from a
1562 a8083063 Iustin Pop
  buffer.
1563 a8083063 Iustin Pop

1564 a8083063 Iustin Pop
  """
1565 a8083063 Iustin Pop
  def Dumps(self):
1566 a8083063 Iustin Pop
    """Dump this instance and return the string representation."""
1567 a8083063 Iustin Pop
    buf = StringIO()
1568 a8083063 Iustin Pop
    self.write(buf)
1569 a8083063 Iustin Pop
    return buf.getvalue()
1570 a8083063 Iustin Pop
1571 b39bf4bb Guido Trotter
  @classmethod
1572 b39bf4bb Guido Trotter
  def Loads(cls, data):
1573 a8083063 Iustin Pop
    """Load data from a string."""
1574 a8083063 Iustin Pop
    buf = StringIO(data)
1575 b39bf4bb Guido Trotter
    cfp = cls()
1576 a8083063 Iustin Pop
    cfp.readfp(buf)
1577 a8083063 Iustin Pop
    return cfp