Statistics
| Branch: | Tag: | Revision:

root / lib / objects.py @ 5b49ed09

History | View | Annotate | Download (44.8 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 0007f3ab Andrea Spadaccini
# pylint: disable=E0203,W0201,R0902
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 0007f3ab Andrea Spadaccini
# R0902: Allow instances of these objects to have more than 20 attributes
37 0007f3ab Andrea Spadaccini
38 a8083063 Iustin Pop
import ConfigParser
39 5c947f38 Iustin Pop
import re
40 5bf7b5cf Iustin Pop
import copy
41 e11a1b77 Adeodato Simo
import time
42 d5835922 Michael Hanselmann
from cStringIO import StringIO
43 a8083063 Iustin Pop
44 a8083063 Iustin Pop
from ganeti import errors
45 5c947f38 Iustin Pop
from ganeti import constants
46 0007f3ab Andrea Spadaccini
from ganeti import netutils
47 a8083063 Iustin Pop
48 f4c9af7a Guido Trotter
from socket import AF_INET
49 f4c9af7a Guido Trotter
50 a8083063 Iustin Pop
51 a8083063 Iustin Pop
__all__ = ["ConfigObject", "ConfigData", "NIC", "Disk", "Instance",
52 24a3707f Guido Trotter
           "OS", "Node", "NodeGroup", "Cluster", "FillDict"]
53 a8083063 Iustin Pop
54 d693c864 Iustin Pop
_TIMESTAMPS = ["ctime", "mtime"]
55 e1dcc53a Iustin Pop
_UUID = ["uuid"]
56 96acbc09 Michael Hanselmann
57 8d8d650c Michael Hanselmann
58 e11ddf13 Iustin Pop
def FillDict(defaults_dict, custom_dict, skip_keys=None):
59 29921401 Iustin Pop
  """Basic function to apply settings on top a default dict.
60 abe609b2 Guido Trotter

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

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

85 6e34b628 Guido Trotter
  @type target: dict of dicts
86 6e34b628 Guido Trotter
  @param target: {group: {parameter: value}}
87 6e34b628 Guido Trotter
  @type defaults: dict
88 6e34b628 Guido Trotter
  @param defaults: default parameter values
89 6e34b628 Guido Trotter

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

102 a8083063 Iustin Pop
  It has the following properties:
103 a8083063 Iustin Pop

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

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

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

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

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

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

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

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

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

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

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

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

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

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

235 90d726a8 Iustin Pop
    This method will be called at configuration load time, and its
236 90d726a8 Iustin Pop
    implementation will be object dependent.
237 560428be Guido Trotter

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

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

253 5c947f38 Iustin Pop
    If the tag is invalid, an errors.TagError will be raised. The
254 5c947f38 Iustin Pop
    function has no return value.
255 5c947f38 Iustin Pop

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

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

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

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

300 ff9c047c Iustin Pop
    This replaces the tags set with a list.
301 ff9c047c Iustin Pop

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

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

324 061af273 Andrea Spadaccini
  @ivar name: master name
325 061af273 Andrea Spadaccini
  @ivar ip: master IP
326 061af273 Andrea Spadaccini
  @ivar netmask: master netmask
327 061af273 Andrea Spadaccini
  @ivar netdev: master network device
328 061af273 Andrea Spadaccini
  @ivar ip_family: master IP family
329 061af273 Andrea Spadaccini

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

354 ff9c047c Iustin Pop
    This just replaces the list of instances, nodes and the cluster
355 ff9c047c Iustin Pop
    with standard python types.
356 ff9c047c Iustin Pop

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

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

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

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

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

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

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

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

461 e51db2a6 Iustin Pop
    @warning: The path returned is not a normalized pathname; callers
462 e51db2a6 Iustin Pop
        should check that it is a valid path.
463 e51db2a6 Iustin Pop

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

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

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

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

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

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

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

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

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

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

560 6d33a6eb Iustin Pop
    This only works for VG-based disks.
561 6d33a6eb Iustin Pop

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

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

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

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

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

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

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

615 0402302c Iustin Pop
    Arguments:
616 0402302c Iustin Pop
      - target_node: the node we wish to configure for
617 0402302c Iustin Pop
      - nodes_ip: a mapping of node name to ip
618 0402302c Iustin Pop

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

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

653 ff9c047c Iustin Pop
    This replaces the children lists of objects with lists of
654 ff9c047c Iustin Pop
    standard python types.
655 ff9c047c Iustin Pop

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

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

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

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

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

758 cfcc5c6d Iustin Pop
    This is a simple wrapper over _ComputeAllNodes.
759 cfcc5c6d Iustin Pop

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

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

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

799 c41eea6e Iustin Pop
    This function figures out what logical volumes should belong on
800 c41eea6e Iustin Pop
    which nodes, recursing through a device tree.
801 a8083063 Iustin Pop

802 c41eea6e Iustin Pop
    @param lvmap: optional dictionary to receive the
803 c41eea6e Iustin Pop
        'node' : ['lv', ...] data.
804 a8083063 Iustin Pop

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

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

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

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

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

867 ff9c047c Iustin Pop
    This replaces the children lists of objects with lists of standard
868 ff9c047c Iustin Pop
    python types.
869 ff9c047c Iustin Pop

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

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

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

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

917 870dc44c Iustin Pop
  @type VARIANT_DELIM: string
918 870dc44c Iustin Pop
  @cvar VARIANT_DELIM: the variant delimiter
919 870dc44c Iustin Pop

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

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

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

955 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
956 870dc44c Iustin Pop

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

964 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
965 870dc44c Iustin Pop

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

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

1021 c60abd62 Guido Trotter
    This discards the members object, which gets recalculated and is only kept
1022 c60abd62 Guido Trotter
    in memory.
1023 24a3707f Guido Trotter

1024 24a3707f Guido Trotter
    """
1025 24a3707f Guido Trotter
    mydict = super(NodeGroup, self).ToDict()
1026 24a3707f Guido Trotter
    del mydict["members"]
1027 24a3707f Guido Trotter
    return mydict
1028 24a3707f Guido Trotter
1029 24a3707f Guido Trotter
  @classmethod
1030 24a3707f Guido Trotter
  def FromDict(cls, val):
1031 24a3707f Guido Trotter
    """Custom function for nodegroup.
1032 24a3707f Guido Trotter

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

1035 24a3707f Guido Trotter
    """
1036 24a3707f Guido Trotter
    obj = super(NodeGroup, cls).FromDict(val)
1037 24a3707f Guido Trotter
    obj.members = []
1038 24a3707f Guido Trotter
    return obj
1039 24a3707f Guido Trotter
1040 095e71aa René Nussbaumer
  def UpgradeConfig(self):
1041 095e71aa René Nussbaumer
    """Fill defaults for missing configuration values.
1042 095e71aa René Nussbaumer

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

1061 095e71aa René Nussbaumer
    @type node: L{objects.Node}
1062 095e71aa René Nussbaumer
    @param node: A Node object to fill
1063 095e71aa René Nussbaumer
    @return a copy of the node's ndparams with defaults filled
1064 095e71aa René Nussbaumer

1065 095e71aa René Nussbaumer
    """
1066 095e71aa René Nussbaumer
    return self.SimpleFillND(node.ndparams)
1067 095e71aa René Nussbaumer
1068 095e71aa René Nussbaumer
  def SimpleFillND(self, ndparams):
1069 095e71aa René Nussbaumer
    """Fill a given ndparams dict with defaults.
1070 095e71aa René Nussbaumer

1071 095e71aa René Nussbaumer
    @type ndparams: dict
1072 095e71aa René Nussbaumer
    @param ndparams: the dict to fill
1073 095e71aa René Nussbaumer
    @rtype: dict
1074 095e71aa René Nussbaumer
    @return: a copy of the passed in ndparams with missing keys filled
1075 e6e88de6 Adeodato Simo
        from the node group defaults
1076 095e71aa René Nussbaumer

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

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

1211 319856a9 Michael Hanselmann
    """
1212 b60ae2ca Iustin Pop
    mydict = super(Cluster, self).ToDict()
1213 319856a9 Michael Hanselmann
    mydict["tcpudp_port_pool"] = list(self.tcpudp_port_pool)
1214 319856a9 Michael Hanselmann
    return mydict
1215 319856a9 Michael Hanselmann
1216 319856a9 Michael Hanselmann
  @classmethod
1217 319856a9 Michael Hanselmann
  def FromDict(cls, val):
1218 319856a9 Michael Hanselmann
    """Custom function for cluster.
1219 319856a9 Michael Hanselmann

1220 319856a9 Michael Hanselmann
    """
1221 b60ae2ca Iustin Pop
    obj = super(Cluster, cls).FromDict(val)
1222 319856a9 Michael Hanselmann
    if not isinstance(obj.tcpudp_port_pool, set):
1223 319856a9 Michael Hanselmann
      obj.tcpudp_port_pool = set(obj.tcpudp_port_pool)
1224 319856a9 Michael Hanselmann
    return obj
1225 319856a9 Michael Hanselmann
1226 d63479b5 Iustin Pop
  def GetHVDefaults(self, hypervisor, os_name=None, skip_keys=None):
1227 d63479b5 Iustin Pop
    """Get the default hypervisor parameters for the cluster.
1228 d63479b5 Iustin Pop

1229 d63479b5 Iustin Pop
    @param hypervisor: the hypervisor name
1230 d63479b5 Iustin Pop
    @param os_name: if specified, we'll also update the defaults for this OS
1231 d63479b5 Iustin Pop
    @param skip_keys: if passed, list of keys not to use
1232 d63479b5 Iustin Pop
    @return: the defaults dict
1233 d63479b5 Iustin Pop

1234 d63479b5 Iustin Pop
    """
1235 d63479b5 Iustin Pop
    if skip_keys is None:
1236 d63479b5 Iustin Pop
      skip_keys = []
1237 d63479b5 Iustin Pop
1238 d63479b5 Iustin Pop
    fill_stack = [self.hvparams.get(hypervisor, {})]
1239 d63479b5 Iustin Pop
    if os_name is not None:
1240 d63479b5 Iustin Pop
      os_hvp = self.os_hvp.get(os_name, {}).get(hypervisor, {})
1241 d63479b5 Iustin Pop
      fill_stack.append(os_hvp)
1242 d63479b5 Iustin Pop
1243 d63479b5 Iustin Pop
    ret_dict = {}
1244 d63479b5 Iustin Pop
    for o_dict in fill_stack:
1245 d63479b5 Iustin Pop
      ret_dict = FillDict(ret_dict, o_dict, skip_keys=skip_keys)
1246 d63479b5 Iustin Pop
1247 d63479b5 Iustin Pop
    return ret_dict
1248 d63479b5 Iustin Pop
1249 73e0328b Iustin Pop
  def SimpleFillHV(self, hv_name, os_name, hvparams, skip_globals=False):
1250 73e0328b Iustin Pop
    """Fill a given hvparams dict with cluster defaults.
1251 73e0328b Iustin Pop

1252 73e0328b Iustin Pop
    @type hv_name: string
1253 73e0328b Iustin Pop
    @param hv_name: the hypervisor to use
1254 73e0328b Iustin Pop
    @type os_name: string
1255 73e0328b Iustin Pop
    @param os_name: the OS to use for overriding the hypervisor defaults
1256 73e0328b Iustin Pop
    @type skip_globals: boolean
1257 73e0328b Iustin Pop
    @param skip_globals: if True, the global hypervisor parameters will
1258 73e0328b Iustin Pop
        not be filled
1259 73e0328b Iustin Pop
    @rtype: dict
1260 73e0328b Iustin Pop
    @return: a copy of the given hvparams with missing keys filled from
1261 73e0328b Iustin Pop
        the cluster defaults
1262 73e0328b Iustin Pop

1263 73e0328b Iustin Pop
    """
1264 73e0328b Iustin Pop
    if skip_globals:
1265 73e0328b Iustin Pop
      skip_keys = constants.HVC_GLOBALS
1266 73e0328b Iustin Pop
    else:
1267 73e0328b Iustin Pop
      skip_keys = []
1268 73e0328b Iustin Pop
1269 73e0328b Iustin Pop
    def_dict = self.GetHVDefaults(hv_name, os_name, skip_keys=skip_keys)
1270 73e0328b Iustin Pop
    return FillDict(def_dict, hvparams, skip_keys=skip_keys)
1271 d63479b5 Iustin Pop
1272 7736a5f2 Iustin Pop
  def FillHV(self, instance, skip_globals=False):
1273 73e0328b Iustin Pop
    """Fill an instance's hvparams 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 7736a5f2 Iustin Pop
    @type skip_globals: boolean
1278 7736a5f2 Iustin Pop
    @param skip_globals: if True, the global hypervisor parameters will
1279 7736a5f2 Iustin Pop
        not be filled
1280 5bf7b5cf Iustin Pop
    @rtype: dict
1281 5bf7b5cf Iustin Pop
    @return: a copy of the instance's hvparams with missing keys filled from
1282 5bf7b5cf Iustin Pop
        the cluster defaults
1283 5bf7b5cf Iustin Pop

1284 5bf7b5cf Iustin Pop
    """
1285 73e0328b Iustin Pop
    return self.SimpleFillHV(instance.hypervisor, instance.os,
1286 73e0328b Iustin Pop
                             instance.hvparams, skip_globals)
1287 17463d22 René Nussbaumer
1288 73e0328b Iustin Pop
  def SimpleFillBE(self, beparams):
1289 73e0328b Iustin Pop
    """Fill a given beparams dict with cluster defaults.
1290 73e0328b Iustin Pop

1291 06596a60 Guido Trotter
    @type beparams: dict
1292 06596a60 Guido Trotter
    @param beparams: the dict to fill
1293 73e0328b Iustin Pop
    @rtype: dict
1294 73e0328b Iustin Pop
    @return: a copy of the passed in beparams with missing keys filled
1295 73e0328b Iustin Pop
        from the cluster defaults
1296 73e0328b Iustin Pop

1297 73e0328b Iustin Pop
    """
1298 73e0328b Iustin Pop
    return FillDict(self.beparams.get(constants.PP_DEFAULT, {}), beparams)
1299 5bf7b5cf Iustin Pop
1300 5bf7b5cf Iustin Pop
  def FillBE(self, instance):
1301 73e0328b Iustin Pop
    """Fill an instance's beparams dict with cluster defaults.
1302 5bf7b5cf Iustin Pop

1303 a2a24f4c Guido Trotter
    @type instance: L{objects.Instance}
1304 5bf7b5cf Iustin Pop
    @param instance: the instance parameter to fill
1305 5bf7b5cf Iustin Pop
    @rtype: dict
1306 5bf7b5cf Iustin Pop
    @return: a copy of the instance's beparams with missing keys filled from
1307 5bf7b5cf Iustin Pop
        the cluster defaults
1308 5bf7b5cf Iustin Pop

1309 5bf7b5cf Iustin Pop
    """
1310 73e0328b Iustin Pop
    return self.SimpleFillBE(instance.beparams)
1311 73e0328b Iustin Pop
1312 73e0328b Iustin Pop
  def SimpleFillNIC(self, nicparams):
1313 73e0328b Iustin Pop
    """Fill a given nicparams dict with cluster defaults.
1314 73e0328b Iustin Pop

1315 06596a60 Guido Trotter
    @type nicparams: dict
1316 06596a60 Guido Trotter
    @param nicparams: the dict to fill
1317 73e0328b Iustin Pop
    @rtype: dict
1318 73e0328b Iustin Pop
    @return: a copy of the passed in nicparams with missing keys filled
1319 73e0328b Iustin Pop
        from the cluster defaults
1320 73e0328b Iustin Pop

1321 73e0328b Iustin Pop
    """
1322 73e0328b Iustin Pop
    return FillDict(self.nicparams.get(constants.PP_DEFAULT, {}), nicparams)
1323 5bf7b5cf Iustin Pop
1324 1bdcbbab Iustin Pop
  def SimpleFillOS(self, os_name, os_params):
1325 1bdcbbab Iustin Pop
    """Fill an instance's osparams dict with cluster defaults.
1326 1bdcbbab Iustin Pop

1327 1bdcbbab Iustin Pop
    @type os_name: string
1328 1bdcbbab Iustin Pop
    @param os_name: the OS name to use
1329 1bdcbbab Iustin Pop
    @type os_params: dict
1330 1bdcbbab Iustin Pop
    @param os_params: the dict to fill with default values
1331 1bdcbbab Iustin Pop
    @rtype: dict
1332 1bdcbbab Iustin Pop
    @return: a copy of the instance's osparams with missing keys filled from
1333 1bdcbbab Iustin Pop
        the cluster defaults
1334 1bdcbbab Iustin Pop

1335 1bdcbbab Iustin Pop
    """
1336 1bdcbbab Iustin Pop
    name_only = os_name.split("+", 1)[0]
1337 1bdcbbab Iustin Pop
    # base OS
1338 1bdcbbab Iustin Pop
    result = self.osparams.get(name_only, {})
1339 1bdcbbab Iustin Pop
    # OS with variant
1340 1bdcbbab Iustin Pop
    result = FillDict(result, self.osparams.get(os_name, {}))
1341 1bdcbbab Iustin Pop
    # specified params
1342 1bdcbbab Iustin Pop
    return FillDict(result, os_params)
1343 1bdcbbab Iustin Pop
1344 095e71aa René Nussbaumer
  def FillND(self, node, nodegroup):
1345 ce523de1 Michael Hanselmann
    """Return filled out ndparams for L{objects.NodeGroup} and L{objects.Node}
1346 095e71aa René Nussbaumer

1347 095e71aa René Nussbaumer
    @type node: L{objects.Node}
1348 095e71aa René Nussbaumer
    @param node: A Node object to fill
1349 095e71aa René Nussbaumer
    @type nodegroup: L{objects.NodeGroup}
1350 095e71aa René Nussbaumer
    @param nodegroup: A Node object to fill
1351 095e71aa René Nussbaumer
    @return a copy of the node's ndparams with defaults filled
1352 095e71aa René Nussbaumer

1353 095e71aa René Nussbaumer
    """
1354 095e71aa René Nussbaumer
    return self.SimpleFillND(nodegroup.FillND(node))
1355 095e71aa René Nussbaumer
1356 095e71aa René Nussbaumer
  def SimpleFillND(self, ndparams):
1357 095e71aa René Nussbaumer
    """Fill a given ndparams dict with defaults.
1358 095e71aa René Nussbaumer

1359 095e71aa René Nussbaumer
    @type ndparams: dict
1360 095e71aa René Nussbaumer
    @param ndparams: the dict to fill
1361 095e71aa René Nussbaumer
    @rtype: dict
1362 095e71aa René Nussbaumer
    @return: a copy of the passed in ndparams with missing keys filled
1363 095e71aa René Nussbaumer
        from the cluster defaults
1364 095e71aa René Nussbaumer

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

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

1407 eb630f50 Michael Hanselmann
  """
1408 eb630f50 Michael Hanselmann
  __slots__ = [
1409 eb630f50 Michael Hanselmann
    "key_name",
1410 eb630f50 Michael Hanselmann
    "ca_pem",
1411 a5310c2a Michael Hanselmann
    "compress",
1412 af1d39b1 Michael Hanselmann
    "magic",
1413 855d2fc7 Michael Hanselmann
    "ipv6",
1414 4478301b Michael Hanselmann
    "connect_timeout",
1415 eb630f50 Michael Hanselmann
    ]
1416 eb630f50 Michael Hanselmann
1417 eb630f50 Michael Hanselmann
1418 18d750b9 Guido Trotter
class ConfdRequest(ConfigObject):
1419 18d750b9 Guido Trotter
  """Object holding a confd request.
1420 18d750b9 Guido Trotter

1421 18d750b9 Guido Trotter
  @ivar protocol: confd protocol version
1422 18d750b9 Guido Trotter
  @ivar type: confd query type
1423 18d750b9 Guido Trotter
  @ivar query: query request
1424 18d750b9 Guido Trotter
  @ivar rsalt: requested reply salt
1425 18d750b9 Guido Trotter

1426 18d750b9 Guido Trotter
  """
1427 18d750b9 Guido Trotter
  __slots__ = [
1428 18d750b9 Guido Trotter
    "protocol",
1429 18d750b9 Guido Trotter
    "type",
1430 18d750b9 Guido Trotter
    "query",
1431 18d750b9 Guido Trotter
    "rsalt",
1432 18d750b9 Guido Trotter
    ]
1433 18d750b9 Guido Trotter
1434 18d750b9 Guido Trotter
1435 18d750b9 Guido Trotter
class ConfdReply(ConfigObject):
1436 18d750b9 Guido Trotter
  """Object holding a confd reply.
1437 18d750b9 Guido Trotter

1438 18d750b9 Guido Trotter
  @ivar protocol: confd protocol version
1439 18d750b9 Guido Trotter
  @ivar status: reply status code (ok, error)
1440 18d750b9 Guido Trotter
  @ivar answer: confd query reply
1441 18d750b9 Guido Trotter
  @ivar serial: configuration serial number
1442 18d750b9 Guido Trotter

1443 18d750b9 Guido Trotter
  """
1444 18d750b9 Guido Trotter
  __slots__ = [
1445 18d750b9 Guido Trotter
    "protocol",
1446 18d750b9 Guido Trotter
    "status",
1447 18d750b9 Guido Trotter
    "answer",
1448 18d750b9 Guido Trotter
    "serial",
1449 18d750b9 Guido Trotter
    ]
1450 18d750b9 Guido Trotter
1451 18d750b9 Guido Trotter
1452 707f23b5 Michael Hanselmann
class QueryFieldDefinition(ConfigObject):
1453 707f23b5 Michael Hanselmann
  """Object holding a query field definition.
1454 707f23b5 Michael Hanselmann

1455 24d6d3e2 Michael Hanselmann
  @ivar name: Field name
1456 707f23b5 Michael Hanselmann
  @ivar title: Human-readable title
1457 707f23b5 Michael Hanselmann
  @ivar kind: Field type
1458 1ae17369 Michael Hanselmann
  @ivar doc: Human-readable description
1459 707f23b5 Michael Hanselmann

1460 707f23b5 Michael Hanselmann
  """
1461 707f23b5 Michael Hanselmann
  __slots__ = [
1462 707f23b5 Michael Hanselmann
    "name",
1463 707f23b5 Michael Hanselmann
    "title",
1464 707f23b5 Michael Hanselmann
    "kind",
1465 1ae17369 Michael Hanselmann
    "doc",
1466 707f23b5 Michael Hanselmann
    ]
1467 707f23b5 Michael Hanselmann
1468 707f23b5 Michael Hanselmann
1469 0538c375 Michael Hanselmann
class _QueryResponseBase(ConfigObject):
1470 0538c375 Michael Hanselmann
  __slots__ = [
1471 0538c375 Michael Hanselmann
    "fields",
1472 0538c375 Michael Hanselmann
    ]
1473 0538c375 Michael Hanselmann
1474 0538c375 Michael Hanselmann
  def ToDict(self):
1475 0538c375 Michael Hanselmann
    """Custom function for serializing.
1476 0538c375 Michael Hanselmann

1477 0538c375 Michael Hanselmann
    """
1478 0538c375 Michael Hanselmann
    mydict = super(_QueryResponseBase, self).ToDict()
1479 0538c375 Michael Hanselmann
    mydict["fields"] = self._ContainerToDicts(mydict["fields"])
1480 0538c375 Michael Hanselmann
    return mydict
1481 0538c375 Michael Hanselmann
1482 0538c375 Michael Hanselmann
  @classmethod
1483 0538c375 Michael Hanselmann
  def FromDict(cls, val):
1484 0538c375 Michael Hanselmann
    """Custom function for de-serializing.
1485 0538c375 Michael Hanselmann

1486 0538c375 Michael Hanselmann
    """
1487 0538c375 Michael Hanselmann
    obj = super(_QueryResponseBase, cls).FromDict(val)
1488 0538c375 Michael Hanselmann
    obj.fields = cls._ContainerFromDicts(obj.fields, list, QueryFieldDefinition)
1489 0538c375 Michael Hanselmann
    return obj
1490 0538c375 Michael Hanselmann
1491 0538c375 Michael Hanselmann
1492 24d6d3e2 Michael Hanselmann
class QueryRequest(ConfigObject):
1493 24d6d3e2 Michael Hanselmann
  """Object holding a query request.
1494 24d6d3e2 Michael Hanselmann

1495 24d6d3e2 Michael Hanselmann
  """
1496 24d6d3e2 Michael Hanselmann
  __slots__ = [
1497 24d6d3e2 Michael Hanselmann
    "what",
1498 24d6d3e2 Michael Hanselmann
    "fields",
1499 2e5c33db Iustin Pop
    "qfilter",
1500 24d6d3e2 Michael Hanselmann
    ]
1501 24d6d3e2 Michael Hanselmann
1502 24d6d3e2 Michael Hanselmann
1503 0538c375 Michael Hanselmann
class QueryResponse(_QueryResponseBase):
1504 24d6d3e2 Michael Hanselmann
  """Object holding the response to a query.
1505 24d6d3e2 Michael Hanselmann

1506 24d6d3e2 Michael Hanselmann
  @ivar fields: List of L{QueryFieldDefinition} objects
1507 24d6d3e2 Michael Hanselmann
  @ivar data: Requested data
1508 24d6d3e2 Michael Hanselmann

1509 24d6d3e2 Michael Hanselmann
  """
1510 24d6d3e2 Michael Hanselmann
  __slots__ = [
1511 24d6d3e2 Michael Hanselmann
    "data",
1512 24d6d3e2 Michael Hanselmann
    ]
1513 24d6d3e2 Michael Hanselmann
1514 24d6d3e2 Michael Hanselmann
1515 24d6d3e2 Michael Hanselmann
class QueryFieldsRequest(ConfigObject):
1516 24d6d3e2 Michael Hanselmann
  """Object holding a request for querying available fields.
1517 24d6d3e2 Michael Hanselmann

1518 24d6d3e2 Michael Hanselmann
  """
1519 24d6d3e2 Michael Hanselmann
  __slots__ = [
1520 24d6d3e2 Michael Hanselmann
    "what",
1521 24d6d3e2 Michael Hanselmann
    "fields",
1522 24d6d3e2 Michael Hanselmann
    ]
1523 24d6d3e2 Michael Hanselmann
1524 24d6d3e2 Michael Hanselmann
1525 0538c375 Michael Hanselmann
class QueryFieldsResponse(_QueryResponseBase):
1526 24d6d3e2 Michael Hanselmann
  """Object holding the response to a query for fields.
1527 24d6d3e2 Michael Hanselmann

1528 24d6d3e2 Michael Hanselmann
  @ivar fields: List of L{QueryFieldDefinition} objects
1529 24d6d3e2 Michael Hanselmann

1530 24d6d3e2 Michael Hanselmann
  """
1531 24d6d3e2 Michael Hanselmann
  __slots__ = [
1532 24d6d3e2 Michael Hanselmann
    ]
1533 24d6d3e2 Michael Hanselmann
1534 24d6d3e2 Michael Hanselmann
1535 6a1434d7 Andrea Spadaccini
class MigrationStatus(ConfigObject):
1536 6a1434d7 Andrea Spadaccini
  """Object holding the status of a migration.
1537 6a1434d7 Andrea Spadaccini

1538 6a1434d7 Andrea Spadaccini
  """
1539 6a1434d7 Andrea Spadaccini
  __slots__ = [
1540 6a1434d7 Andrea Spadaccini
    "status",
1541 6a1434d7 Andrea Spadaccini
    "transferred_ram",
1542 6a1434d7 Andrea Spadaccini
    "total_ram",
1543 6a1434d7 Andrea Spadaccini
    ]
1544 6a1434d7 Andrea Spadaccini
1545 6a1434d7 Andrea Spadaccini
1546 25ce3ec4 Michael Hanselmann
class InstanceConsole(ConfigObject):
1547 25ce3ec4 Michael Hanselmann
  """Object describing how to access the console of an instance.
1548 25ce3ec4 Michael Hanselmann

1549 25ce3ec4 Michael Hanselmann
  """
1550 25ce3ec4 Michael Hanselmann
  __slots__ = [
1551 25ce3ec4 Michael Hanselmann
    "instance",
1552 25ce3ec4 Michael Hanselmann
    "kind",
1553 25ce3ec4 Michael Hanselmann
    "message",
1554 25ce3ec4 Michael Hanselmann
    "host",
1555 25ce3ec4 Michael Hanselmann
    "port",
1556 25ce3ec4 Michael Hanselmann
    "user",
1557 25ce3ec4 Michael Hanselmann
    "command",
1558 25ce3ec4 Michael Hanselmann
    "display",
1559 25ce3ec4 Michael Hanselmann
    ]
1560 25ce3ec4 Michael Hanselmann
1561 25ce3ec4 Michael Hanselmann
  def Validate(self):
1562 25ce3ec4 Michael Hanselmann
    """Validates contents of this object.
1563 25ce3ec4 Michael Hanselmann

1564 25ce3ec4 Michael Hanselmann
    """
1565 25ce3ec4 Michael Hanselmann
    assert self.kind in constants.CONS_ALL, "Unknown console type"
1566 25ce3ec4 Michael Hanselmann
    assert self.instance, "Missing instance name"
1567 4d2cdb5a Andrea Spadaccini
    assert self.message or self.kind in [constants.CONS_SSH,
1568 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1569 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_VNC]
1570 25ce3ec4 Michael Hanselmann
    assert self.host or self.kind == constants.CONS_MESSAGE
1571 25ce3ec4 Michael Hanselmann
    assert self.port or self.kind in [constants.CONS_MESSAGE,
1572 25ce3ec4 Michael Hanselmann
                                      constants.CONS_SSH]
1573 25ce3ec4 Michael Hanselmann
    assert self.user or self.kind in [constants.CONS_MESSAGE,
1574 4d2cdb5a Andrea Spadaccini
                                      constants.CONS_SPICE,
1575 25ce3ec4 Michael Hanselmann
                                      constants.CONS_VNC]
1576 25ce3ec4 Michael Hanselmann
    assert self.command or self.kind in [constants.CONS_MESSAGE,
1577 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1578 25ce3ec4 Michael Hanselmann
                                         constants.CONS_VNC]
1579 25ce3ec4 Michael Hanselmann
    assert self.display or self.kind in [constants.CONS_MESSAGE,
1580 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1581 25ce3ec4 Michael Hanselmann
                                         constants.CONS_SSH]
1582 25ce3ec4 Michael Hanselmann
    return True
1583 25ce3ec4 Michael Hanselmann
1584 25ce3ec4 Michael Hanselmann
1585 a8083063 Iustin Pop
class SerializableConfigParser(ConfigParser.SafeConfigParser):
1586 a8083063 Iustin Pop
  """Simple wrapper over ConfigParse that allows serialization.
1587 a8083063 Iustin Pop

1588 a8083063 Iustin Pop
  This class is basically ConfigParser.SafeConfigParser with two
1589 a8083063 Iustin Pop
  additional methods that allow it to serialize/unserialize to/from a
1590 a8083063 Iustin Pop
  buffer.
1591 a8083063 Iustin Pop

1592 a8083063 Iustin Pop
  """
1593 a8083063 Iustin Pop
  def Dumps(self):
1594 a8083063 Iustin Pop
    """Dump this instance and return the string representation."""
1595 a8083063 Iustin Pop
    buf = StringIO()
1596 a8083063 Iustin Pop
    self.write(buf)
1597 a8083063 Iustin Pop
    return buf.getvalue()
1598 a8083063 Iustin Pop
1599 b39bf4bb Guido Trotter
  @classmethod
1600 b39bf4bb Guido Trotter
  def Loads(cls, data):
1601 a8083063 Iustin Pop
    """Load data from a string."""
1602 a8083063 Iustin Pop
    buf = StringIO(data)
1603 b39bf4bb Guido Trotter
    cfp = cls()
1604 a8083063 Iustin Pop
    cfp.readfp(buf)
1605 a8083063 Iustin Pop
    return cfp