Statistics
| Branch: | Tag: | Revision:

root / lib / objects.py @ 93b19295

History | View | Annotate | Download (57.4 kB)

1 2f31098c Iustin Pop
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 2cc673a3 Iustin Pop
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 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 2ed0e208 Iustin Pop
# objects.py which doesn't explicitly 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 32683096 René Nussbaumer
from ganeti import objectutils
48 32017174 Agata Murawska
from ganeti import utils
49 a8083063 Iustin Pop
50 f4c9af7a Guido Trotter
from socket import AF_INET
51 f4c9af7a Guido Trotter
52 a8083063 Iustin Pop
53 a8083063 Iustin Pop
__all__ = ["ConfigObject", "ConfigData", "NIC", "Disk", "Instance",
54 24a3707f Guido Trotter
           "OS", "Node", "NodeGroup", "Cluster", "FillDict"]
55 a8083063 Iustin Pop
56 d693c864 Iustin Pop
_TIMESTAMPS = ["ctime", "mtime"]
57 e1dcc53a Iustin Pop
_UUID = ["uuid"]
58 96acbc09 Michael Hanselmann
59 8d8d650c Michael Hanselmann
60 e11ddf13 Iustin Pop
def FillDict(defaults_dict, custom_dict, skip_keys=None):
61 29921401 Iustin Pop
  """Basic function to apply settings on top a default dict.
62 abe609b2 Guido Trotter

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

72 29921401 Iustin Pop
  """
73 29921401 Iustin Pop
  ret_dict = copy.deepcopy(defaults_dict)
74 29921401 Iustin Pop
  ret_dict.update(custom_dict)
75 e11ddf13 Iustin Pop
  if skip_keys:
76 e11ddf13 Iustin Pop
    for k in skip_keys:
77 e11ddf13 Iustin Pop
      try:
78 e11ddf13 Iustin Pop
        del ret_dict[k]
79 e11ddf13 Iustin Pop
      except KeyError:
80 e11ddf13 Iustin Pop
        pass
81 29921401 Iustin Pop
  return ret_dict
82 a8083063 Iustin Pop
83 6e34b628 Guido Trotter
84 2cc673a3 Iustin Pop
def FillIPolicy(default_ipolicy, custom_ipolicy, skip_keys=None):
85 2cc673a3 Iustin Pop
  """Fills an instance policy with defaults.
86 918eb80b Agata Murawska

87 918eb80b Agata Murawska
  """
88 2cc673a3 Iustin Pop
  assert frozenset(default_ipolicy.keys()) == constants.IPOLICY_ALL_KEYS
89 918eb80b Agata Murawska
  ret_dict = {}
90 12378fe3 Iustin Pop
  for key in constants.IPOLICY_ISPECS:
91 2cc673a3 Iustin Pop
    ret_dict[key] = FillDict(default_ipolicy[key],
92 2cc673a3 Iustin Pop
                             custom_ipolicy.get(key, {}),
93 918eb80b Agata Murawska
                             skip_keys=skip_keys)
94 2cc673a3 Iustin Pop
  # list items
95 d04c9d45 Iustin Pop
  for key in [constants.IPOLICY_DTS]:
96 2cc673a3 Iustin Pop
    ret_dict[key] = list(custom_ipolicy.get(key, default_ipolicy[key]))
97 ff6c5e55 Iustin Pop
  # other items which we know we can directly copy (immutables)
98 ff6c5e55 Iustin Pop
  for key in constants.IPOLICY_PARAMETERS:
99 ff6c5e55 Iustin Pop
    ret_dict[key] = custom_ipolicy.get(key, default_ipolicy[key])
100 2cc673a3 Iustin Pop
101 918eb80b Agata Murawska
  return ret_dict
102 918eb80b Agata Murawska
103 918eb80b Agata Murawska
104 57987785 René Nussbaumer
def FillDiskParams(default_dparams, custom_dparams, skip_keys=None):
105 57987785 René Nussbaumer
  """Fills the disk parameter defaults.
106 57987785 René Nussbaumer

107 af9fb4cc René Nussbaumer
  @see: L{FillDict} for parameters and return value
108 57987785 René Nussbaumer

109 57987785 René Nussbaumer
  """
110 57987785 René Nussbaumer
  assert frozenset(default_dparams.keys()) == constants.DISK_TEMPLATES
111 57987785 René Nussbaumer
112 57987785 René Nussbaumer
  return dict((dt, FillDict(default_dparams[dt], custom_dparams.get(dt, {}),
113 57987785 René Nussbaumer
                             skip_keys=skip_keys))
114 57987785 René Nussbaumer
              for dt in constants.DISK_TEMPLATES)
115 57987785 René Nussbaumer
116 57987785 René Nussbaumer
117 6e34b628 Guido Trotter
def UpgradeGroupedParams(target, defaults):
118 6e34b628 Guido Trotter
  """Update all groups for the target parameter.
119 6e34b628 Guido Trotter

120 6e34b628 Guido Trotter
  @type target: dict of dicts
121 6e34b628 Guido Trotter
  @param target: {group: {parameter: value}}
122 6e34b628 Guido Trotter
  @type defaults: dict
123 6e34b628 Guido Trotter
  @param defaults: default parameter values
124 6e34b628 Guido Trotter

125 6e34b628 Guido Trotter
  """
126 6e34b628 Guido Trotter
  if target is None:
127 6e34b628 Guido Trotter
    target = {constants.PP_DEFAULT: defaults}
128 6e34b628 Guido Trotter
  else:
129 6e34b628 Guido Trotter
    for group in target:
130 6e34b628 Guido Trotter
      target[group] = FillDict(defaults, target[group])
131 6e34b628 Guido Trotter
  return target
132 6e34b628 Guido Trotter
133 6e34b628 Guido Trotter
134 8c72ab2b Guido Trotter
def UpgradeBeParams(target):
135 8c72ab2b Guido Trotter
  """Update the be parameters dict to the new format.
136 8c72ab2b Guido Trotter

137 8c72ab2b Guido Trotter
  @type target: dict
138 8c72ab2b Guido Trotter
  @param target: "be" parameters dict
139 8c72ab2b Guido Trotter

140 8c72ab2b Guido Trotter
  """
141 8c72ab2b Guido Trotter
  if constants.BE_MEMORY in target:
142 8c72ab2b Guido Trotter
    memory = target[constants.BE_MEMORY]
143 8c72ab2b Guido Trotter
    target[constants.BE_MAXMEM] = memory
144 8c72ab2b Guido Trotter
    target[constants.BE_MINMEM] = memory
145 b2e233a5 Guido Trotter
    del target[constants.BE_MEMORY]
146 8c72ab2b Guido Trotter
147 8c72ab2b Guido Trotter
148 bc5d0215 Andrea Spadaccini
def UpgradeDiskParams(diskparams):
149 bc5d0215 Andrea Spadaccini
  """Upgrade the disk parameters.
150 bc5d0215 Andrea Spadaccini

151 bc5d0215 Andrea Spadaccini
  @type diskparams: dict
152 bc5d0215 Andrea Spadaccini
  @param diskparams: disk parameters to upgrade
153 bc5d0215 Andrea Spadaccini
  @rtype: dict
154 765ada2b Iustin Pop
  @return: the upgraded disk parameters dict
155 bc5d0215 Andrea Spadaccini

156 bc5d0215 Andrea Spadaccini
  """
157 99ccf8b9 René Nussbaumer
  if not diskparams:
158 99ccf8b9 René Nussbaumer
    result = {}
159 bc5d0215 Andrea Spadaccini
  else:
160 57987785 René Nussbaumer
    result = FillDiskParams(constants.DISK_DT_DEFAULTS, diskparams)
161 bc5d0215 Andrea Spadaccini
162 bc5d0215 Andrea Spadaccini
  return result
163 bc5d0215 Andrea Spadaccini
164 bc5d0215 Andrea Spadaccini
165 2a27dac3 Iustin Pop
def UpgradeNDParams(ndparams):
166 2a27dac3 Iustin Pop
  """Upgrade ndparams structure.
167 2a27dac3 Iustin Pop

168 2a27dac3 Iustin Pop
  @type ndparams: dict
169 2a27dac3 Iustin Pop
  @param ndparams: disk parameters to upgrade
170 2a27dac3 Iustin Pop
  @rtype: dict
171 2a27dac3 Iustin Pop
  @return: the upgraded node parameters dict
172 2a27dac3 Iustin Pop

173 2a27dac3 Iustin Pop
  """
174 2a27dac3 Iustin Pop
  if ndparams is None:
175 2a27dac3 Iustin Pop
    ndparams = {}
176 2a27dac3 Iustin Pop
177 1df4d430 Iustin Pop
  if (constants.ND_OOB_PROGRAM in ndparams and
178 1df4d430 Iustin Pop
      ndparams[constants.ND_OOB_PROGRAM] is None):
179 1df4d430 Iustin Pop
    # will be reset by the line below
180 1df4d430 Iustin Pop
    del ndparams[constants.ND_OOB_PROGRAM]
181 2a27dac3 Iustin Pop
  return FillDict(constants.NDC_DEFAULTS, ndparams)
182 2a27dac3 Iustin Pop
183 2a27dac3 Iustin Pop
184 918eb80b Agata Murawska
def MakeEmptyIPolicy():
185 918eb80b Agata Murawska
  """Create empty IPolicy dictionary.
186 918eb80b Agata Murawska

187 918eb80b Agata Murawska
  """
188 918eb80b Agata Murawska
  return dict([
189 2cc673a3 Iustin Pop
    (constants.ISPECS_MIN, {}),
190 2cc673a3 Iustin Pop
    (constants.ISPECS_MAX, {}),
191 2cc673a3 Iustin Pop
    (constants.ISPECS_STD, {}),
192 918eb80b Agata Murawska
    ])
193 918eb80b Agata Murawska
194 918eb80b Agata Murawska
195 32683096 René Nussbaumer
class ConfigObject(objectutils.ValidatedSlots):
196 a8083063 Iustin Pop
  """A generic config object.
197 a8083063 Iustin Pop

198 a8083063 Iustin Pop
  It has the following properties:
199 a8083063 Iustin Pop

200 a8083063 Iustin Pop
    - provides somewhat safe recursive unpickling and pickling for its classes
201 a8083063 Iustin Pop
    - unset attributes which are defined in slots are always returned
202 a8083063 Iustin Pop
      as None instead of raising an error
203 a8083063 Iustin Pop

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

207 a8083063 Iustin Pop
  """
208 a8083063 Iustin Pop
  __slots__ = []
209 a8083063 Iustin Pop
210 a8083063 Iustin Pop
  def __getattr__(self, name):
211 32683096 René Nussbaumer
    if name not in self.GetAllSlots():
212 3ecf6786 Iustin Pop
      raise AttributeError("Invalid object attribute %s.%s" %
213 3ecf6786 Iustin Pop
                           (type(self).__name__, name))
214 a8083063 Iustin Pop
    return None
215 a8083063 Iustin Pop
216 a8083063 Iustin Pop
  def __setstate__(self, state):
217 32683096 René Nussbaumer
    slots = self.GetAllSlots()
218 a8083063 Iustin Pop
    for name in state:
219 adf385c7 Iustin Pop
      if name in slots:
220 a8083063 Iustin Pop
        setattr(self, name, state[name])
221 a8083063 Iustin Pop
222 32683096 René Nussbaumer
  def Validate(self):
223 32683096 René Nussbaumer
    """Validates the slots.
224 adf385c7 Iustin Pop

225 adf385c7 Iustin Pop
    """
226 415feb2e René Nussbaumer
227 ff9c047c Iustin Pop
  def ToDict(self):
228 ff9c047c Iustin Pop
    """Convert to a dict holding only standard python types.
229 ff9c047c Iustin Pop

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

236 ff9c047c Iustin Pop
    """
237 4c14965f Guido Trotter
    result = {}
238 32683096 René Nussbaumer
    for name in self.GetAllSlots():
239 4c14965f Guido Trotter
      value = getattr(self, name, None)
240 4c14965f Guido Trotter
      if value is not None:
241 4c14965f Guido Trotter
        result[name] = value
242 4c14965f Guido Trotter
    return result
243 4c14965f Guido Trotter
244 4c14965f Guido Trotter
  __getstate__ = ToDict
245 ff9c047c Iustin Pop
246 ff9c047c Iustin Pop
  @classmethod
247 ff9c047c Iustin Pop
  def FromDict(cls, val):
248 ff9c047c Iustin Pop
    """Create an object from a dictionary.
249 ff9c047c Iustin Pop

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

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

258 ff9c047c Iustin Pop
    """
259 ff9c047c Iustin Pop
    if not isinstance(val, dict):
260 ff9c047c Iustin Pop
      raise errors.ConfigurationError("Invalid object passed to FromDict:"
261 ff9c047c Iustin Pop
                                      " expected dict, got %s" % type(val))
262 319856a9 Michael Hanselmann
    val_str = dict([(str(k), v) for k, v in val.iteritems()])
263 b459a848 Andrea Spadaccini
    obj = cls(**val_str) # pylint: disable=W0142
264 ff9c047c Iustin Pop
    return obj
265 ff9c047c Iustin Pop
266 ff9c047c Iustin Pop
  @staticmethod
267 ff9c047c Iustin Pop
  def _ContainerToDicts(container):
268 ff9c047c Iustin Pop
    """Convert the elements of a container to standard python types.
269 ff9c047c Iustin Pop

270 ff9c047c Iustin Pop
    This method converts a container with elements derived from
271 ff9c047c Iustin Pop
    ConfigData to standard python types. If the container is a dict,
272 ff9c047c Iustin Pop
    we don't touch the keys, only the values.
273 ff9c047c Iustin Pop

274 ff9c047c Iustin Pop
    """
275 ff9c047c Iustin Pop
    if isinstance(container, dict):
276 ff9c047c Iustin Pop
      ret = dict([(k, v.ToDict()) for k, v in container.iteritems()])
277 ff9c047c Iustin Pop
    elif isinstance(container, (list, tuple, set, frozenset)):
278 ff9c047c Iustin Pop
      ret = [elem.ToDict() for elem in container]
279 ff9c047c Iustin Pop
    else:
280 ff9c047c Iustin Pop
      raise TypeError("Invalid type %s passed to _ContainerToDicts" %
281 ff9c047c Iustin Pop
                      type(container))
282 ff9c047c Iustin Pop
    return ret
283 ff9c047c Iustin Pop
284 ff9c047c Iustin Pop
  @staticmethod
285 ff9c047c Iustin Pop
  def _ContainerFromDicts(source, c_type, e_type):
286 ff9c047c Iustin Pop
    """Convert a container from standard python types.
287 ff9c047c Iustin Pop

288 ff9c047c Iustin Pop
    This method converts a container with standard python types to
289 ff9c047c Iustin Pop
    ConfigData objects. If the container is a dict, we don't touch the
290 ff9c047c Iustin Pop
    keys, only the values.
291 ff9c047c Iustin Pop

292 ff9c047c Iustin Pop
    """
293 ff9c047c Iustin Pop
    if not isinstance(c_type, type):
294 ff9c047c Iustin Pop
      raise TypeError("Container type %s passed to _ContainerFromDicts is"
295 ff9c047c Iustin Pop
                      " not a type" % type(c_type))
296 fe25a79a Guido Trotter
    if source is None:
297 fe25a79a Guido Trotter
      source = c_type()
298 ff9c047c Iustin Pop
    if c_type is dict:
299 ff9c047c Iustin Pop
      ret = dict([(k, e_type.FromDict(v)) for k, v in source.iteritems()])
300 ff9c047c Iustin Pop
    elif c_type in (list, tuple, set, frozenset):
301 ff9c047c Iustin Pop
      ret = c_type([e_type.FromDict(elem) for elem in source])
302 ff9c047c Iustin Pop
    else:
303 ff9c047c Iustin Pop
      raise TypeError("Invalid container type %s passed to"
304 ff9c047c Iustin Pop
                      " _ContainerFromDicts" % c_type)
305 ff9c047c Iustin Pop
    return ret
306 ff9c047c Iustin Pop
307 e8d563f3 Iustin Pop
  def Copy(self):
308 e8d563f3 Iustin Pop
    """Makes a deep copy of the current object and its children.
309 e8d563f3 Iustin Pop

310 e8d563f3 Iustin Pop
    """
311 e8d563f3 Iustin Pop
    dict_form = self.ToDict()
312 e8d563f3 Iustin Pop
    clone_obj = self.__class__.FromDict(dict_form)
313 e8d563f3 Iustin Pop
    return clone_obj
314 e8d563f3 Iustin Pop
315 ff9c047c Iustin Pop
  def __repr__(self):
316 ff9c047c Iustin Pop
    """Implement __repr__ for ConfigObjects."""
317 ff9c047c Iustin Pop
    return repr(self.ToDict())
318 ff9c047c Iustin Pop
319 560428be Guido Trotter
  def UpgradeConfig(self):
320 560428be Guido Trotter
    """Fill defaults for missing configuration values.
321 560428be Guido Trotter

322 90d726a8 Iustin Pop
    This method will be called at configuration load time, and its
323 90d726a8 Iustin Pop
    implementation will be object dependent.
324 560428be Guido Trotter

325 560428be Guido Trotter
    """
326 560428be Guido Trotter
    pass
327 560428be Guido Trotter
328 a8083063 Iustin Pop
329 ec29fe40 Iustin Pop
class TaggableObject(ConfigObject):
330 5c947f38 Iustin Pop
  """An generic class supporting tags.
331 5c947f38 Iustin Pop

332 5c947f38 Iustin Pop
  """
333 154b9580 Balazs Lecz
  __slots__ = ["tags"]
334 b5e5632e Iustin Pop
  VALID_TAG_RE = re.compile("^[\w.+*/:@-]+$")
335 2057f6c7 Iustin Pop
336 b5e5632e Iustin Pop
  @classmethod
337 b5e5632e Iustin Pop
  def ValidateTag(cls, tag):
338 5c947f38 Iustin Pop
    """Check if a tag is valid.
339 5c947f38 Iustin Pop

340 5c947f38 Iustin Pop
    If the tag is invalid, an errors.TagError will be raised. The
341 5c947f38 Iustin Pop
    function has no return value.
342 5c947f38 Iustin Pop

343 5c947f38 Iustin Pop
    """
344 5c947f38 Iustin Pop
    if not isinstance(tag, basestring):
345 3ecf6786 Iustin Pop
      raise errors.TagError("Invalid tag type (not a string)")
346 5c947f38 Iustin Pop
    if len(tag) > constants.MAX_TAG_LEN:
347 319856a9 Michael Hanselmann
      raise errors.TagError("Tag too long (>%d characters)" %
348 319856a9 Michael Hanselmann
                            constants.MAX_TAG_LEN)
349 5c947f38 Iustin Pop
    if not tag:
350 3ecf6786 Iustin Pop
      raise errors.TagError("Tags cannot be empty")
351 b5e5632e Iustin Pop
    if not cls.VALID_TAG_RE.match(tag):
352 3ecf6786 Iustin Pop
      raise errors.TagError("Tag contains invalid characters")
353 5c947f38 Iustin Pop
354 5c947f38 Iustin Pop
  def GetTags(self):
355 5c947f38 Iustin Pop
    """Return the tags list.
356 5c947f38 Iustin Pop

357 5c947f38 Iustin Pop
    """
358 5c947f38 Iustin Pop
    tags = getattr(self, "tags", None)
359 5c947f38 Iustin Pop
    if tags is None:
360 5c947f38 Iustin Pop
      tags = self.tags = set()
361 5c947f38 Iustin Pop
    return tags
362 5c947f38 Iustin Pop
363 5c947f38 Iustin Pop
  def AddTag(self, tag):
364 5c947f38 Iustin Pop
    """Add a new tag.
365 5c947f38 Iustin Pop

366 5c947f38 Iustin Pop
    """
367 5c947f38 Iustin Pop
    self.ValidateTag(tag)
368 5c947f38 Iustin Pop
    tags = self.GetTags()
369 5c947f38 Iustin Pop
    if len(tags) >= constants.MAX_TAGS_PER_OBJ:
370 3ecf6786 Iustin Pop
      raise errors.TagError("Too many tags")
371 5c947f38 Iustin Pop
    self.GetTags().add(tag)
372 5c947f38 Iustin Pop
373 5c947f38 Iustin Pop
  def RemoveTag(self, tag):
374 5c947f38 Iustin Pop
    """Remove a tag.
375 5c947f38 Iustin Pop

376 5c947f38 Iustin Pop
    """
377 5c947f38 Iustin Pop
    self.ValidateTag(tag)
378 5c947f38 Iustin Pop
    tags = self.GetTags()
379 5c947f38 Iustin Pop
    try:
380 5c947f38 Iustin Pop
      tags.remove(tag)
381 5c947f38 Iustin Pop
    except KeyError:
382 3ecf6786 Iustin Pop
      raise errors.TagError("Tag not found")
383 5c947f38 Iustin Pop
384 ff9c047c Iustin Pop
  def ToDict(self):
385 ff9c047c Iustin Pop
    """Taggable-object-specific conversion to standard python types.
386 ff9c047c Iustin Pop

387 ff9c047c Iustin Pop
    This replaces the tags set with a list.
388 ff9c047c Iustin Pop

389 ff9c047c Iustin Pop
    """
390 ff9c047c Iustin Pop
    bo = super(TaggableObject, self).ToDict()
391 ff9c047c Iustin Pop
392 ff9c047c Iustin Pop
    tags = bo.get("tags", None)
393 ff9c047c Iustin Pop
    if isinstance(tags, set):
394 ff9c047c Iustin Pop
      bo["tags"] = list(tags)
395 ff9c047c Iustin Pop
    return bo
396 ff9c047c Iustin Pop
397 ff9c047c Iustin Pop
  @classmethod
398 ff9c047c Iustin Pop
  def FromDict(cls, val):
399 ff9c047c Iustin Pop
    """Custom function for instances.
400 ff9c047c Iustin Pop

401 ff9c047c Iustin Pop
    """
402 ff9c047c Iustin Pop
    obj = super(TaggableObject, cls).FromDict(val)
403 ff9c047c Iustin Pop
    if hasattr(obj, "tags") and isinstance(obj.tags, list):
404 ff9c047c Iustin Pop
      obj.tags = set(obj.tags)
405 ff9c047c Iustin Pop
    return obj
406 ff9c047c Iustin Pop
407 5c947f38 Iustin Pop
408 061af273 Andrea Spadaccini
class MasterNetworkParameters(ConfigObject):
409 061af273 Andrea Spadaccini
  """Network configuration parameters for the master
410 061af273 Andrea Spadaccini

411 061af273 Andrea Spadaccini
  @ivar name: master name
412 061af273 Andrea Spadaccini
  @ivar ip: master IP
413 061af273 Andrea Spadaccini
  @ivar netmask: master netmask
414 061af273 Andrea Spadaccini
  @ivar netdev: master network device
415 061af273 Andrea Spadaccini
  @ivar ip_family: master IP family
416 061af273 Andrea Spadaccini

417 061af273 Andrea Spadaccini
  """
418 061af273 Andrea Spadaccini
  __slots__ = [
419 061af273 Andrea Spadaccini
    "name",
420 061af273 Andrea Spadaccini
    "ip",
421 061af273 Andrea Spadaccini
    "netmask",
422 061af273 Andrea Spadaccini
    "netdev",
423 061af273 Andrea Spadaccini
    "ip_family"
424 061af273 Andrea Spadaccini
    ]
425 061af273 Andrea Spadaccini
426 061af273 Andrea Spadaccini
427 a8083063 Iustin Pop
class ConfigData(ConfigObject):
428 a8083063 Iustin Pop
  """Top-level config object."""
429 3df43542 Guido Trotter
  __slots__ = [
430 3df43542 Guido Trotter
    "version",
431 3df43542 Guido Trotter
    "cluster",
432 3df43542 Guido Trotter
    "nodes",
433 3df43542 Guido Trotter
    "nodegroups",
434 3df43542 Guido Trotter
    "instances",
435 3df43542 Guido Trotter
    "serial_no",
436 3df43542 Guido Trotter
    ] + _TIMESTAMPS
437 a8083063 Iustin Pop
438 ff9c047c Iustin Pop
  def ToDict(self):
439 ff9c047c Iustin Pop
    """Custom function for top-level config data.
440 ff9c047c Iustin Pop

441 ff9c047c Iustin Pop
    This just replaces the list of instances, nodes and the cluster
442 ff9c047c Iustin Pop
    with standard python types.
443 ff9c047c Iustin Pop

444 ff9c047c Iustin Pop
    """
445 ff9c047c Iustin Pop
    mydict = super(ConfigData, self).ToDict()
446 ff9c047c Iustin Pop
    mydict["cluster"] = mydict["cluster"].ToDict()
447 3df43542 Guido Trotter
    for key in "nodes", "instances", "nodegroups":
448 ff9c047c Iustin Pop
      mydict[key] = self._ContainerToDicts(mydict[key])
449 ff9c047c Iustin Pop
450 ff9c047c Iustin Pop
    return mydict
451 ff9c047c Iustin Pop
452 ff9c047c Iustin Pop
  @classmethod
453 ff9c047c Iustin Pop
  def FromDict(cls, val):
454 ff9c047c Iustin Pop
    """Custom function for top-level config data
455 ff9c047c Iustin Pop

456 ff9c047c Iustin Pop
    """
457 ff9c047c Iustin Pop
    obj = super(ConfigData, cls).FromDict(val)
458 ff9c047c Iustin Pop
    obj.cluster = Cluster.FromDict(obj.cluster)
459 ff9c047c Iustin Pop
    obj.nodes = cls._ContainerFromDicts(obj.nodes, dict, Node)
460 ff9c047c Iustin Pop
    obj.instances = cls._ContainerFromDicts(obj.instances, dict, Instance)
461 3df43542 Guido Trotter
    obj.nodegroups = cls._ContainerFromDicts(obj.nodegroups, dict, NodeGroup)
462 ff9c047c Iustin Pop
    return obj
463 ff9c047c Iustin Pop
464 51cb1581 Luca Bigliardi
  def HasAnyDiskOfType(self, dev_type):
465 51cb1581 Luca Bigliardi
    """Check if in there is at disk of the given type in the configuration.
466 51cb1581 Luca Bigliardi

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

472 51cb1581 Luca Bigliardi
    """
473 51cb1581 Luca Bigliardi
    for instance in self.instances.values():
474 51cb1581 Luca Bigliardi
      for disk in instance.disks:
475 51cb1581 Luca Bigliardi
        if disk.IsBasedOnDiskType(dev_type):
476 51cb1581 Luca Bigliardi
          return True
477 51cb1581 Luca Bigliardi
    return False
478 51cb1581 Luca Bigliardi
479 90d726a8 Iustin Pop
  def UpgradeConfig(self):
480 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
481 90d726a8 Iustin Pop

482 90d726a8 Iustin Pop
    """
483 90d726a8 Iustin Pop
    self.cluster.UpgradeConfig()
484 90d726a8 Iustin Pop
    for node in self.nodes.values():
485 90d726a8 Iustin Pop
      node.UpgradeConfig()
486 90d726a8 Iustin Pop
    for instance in self.instances.values():
487 90d726a8 Iustin Pop
      instance.UpgradeConfig()
488 3df43542 Guido Trotter
    if self.nodegroups is None:
489 3df43542 Guido Trotter
      self.nodegroups = {}
490 3df43542 Guido Trotter
    for nodegroup in self.nodegroups.values():
491 3df43542 Guido Trotter
      nodegroup.UpgradeConfig()
492 ee2f0ed4 Luca Bigliardi
    if self.cluster.drbd_usermode_helper is None:
493 ee2f0ed4 Luca Bigliardi
      # To decide if we set an helper let's check if at least one instance has
494 ee2f0ed4 Luca Bigliardi
      # a DRBD disk. This does not cover all the possible scenarios but it
495 ee2f0ed4 Luca Bigliardi
      # gives a good approximation.
496 ee2f0ed4 Luca Bigliardi
      if self.HasAnyDiskOfType(constants.LD_DRBD8):
497 ee2f0ed4 Luca Bigliardi
        self.cluster.drbd_usermode_helper = constants.DEFAULT_DRBD_HELPER
498 90d726a8 Iustin Pop
499 a8083063 Iustin Pop
500 a8083063 Iustin Pop
class NIC(ConfigObject):
501 a8083063 Iustin Pop
  """Config object representing a network card."""
502 1177d70e Guido Trotter
  __slots__ = ["mac", "ip", "nicparams"]
503 a8083063 Iustin Pop
504 255e19d4 Guido Trotter
  @classmethod
505 255e19d4 Guido Trotter
  def CheckParameterSyntax(cls, nicparams):
506 255e19d4 Guido Trotter
    """Check the given parameters for validity.
507 255e19d4 Guido Trotter

508 255e19d4 Guido Trotter
    @type nicparams:  dict
509 255e19d4 Guido Trotter
    @param nicparams: dictionary with parameter names/value
510 255e19d4 Guido Trotter
    @raise errors.ConfigurationError: when a parameter is not valid
511 255e19d4 Guido Trotter

512 255e19d4 Guido Trotter
    """
513 e8448672 Agata Murawska
    if (nicparams[constants.NIC_MODE] not in constants.NIC_VALID_MODES and
514 e8448672 Agata Murawska
        nicparams[constants.NIC_MODE] != constants.VALUE_AUTO):
515 255e19d4 Guido Trotter
      err = "Invalid nic mode: %s" % nicparams[constants.NIC_MODE]
516 255e19d4 Guido Trotter
      raise errors.ConfigurationError(err)
517 255e19d4 Guido Trotter
518 0c9d32c1 Guido Trotter
    if (nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED and
519 255e19d4 Guido Trotter
        not nicparams[constants.NIC_LINK]):
520 255e19d4 Guido Trotter
      err = "Missing bridged nic link"
521 255e19d4 Guido Trotter
      raise errors.ConfigurationError(err)
522 255e19d4 Guido Trotter
523 a8083063 Iustin Pop
524 a8083063 Iustin Pop
class Disk(ConfigObject):
525 a8083063 Iustin Pop
  """Config object representing a block device."""
526 a8083063 Iustin Pop
  __slots__ = ["dev_type", "logical_id", "physical_id",
527 bc5d0215 Andrea Spadaccini
               "children", "iv_name", "size", "mode", "params"]
528 a8083063 Iustin Pop
529 a8083063 Iustin Pop
  def CreateOnSecondary(self):
530 a8083063 Iustin Pop
    """Test if this device needs to be created on a secondary node."""
531 00fb8246 Michael Hanselmann
    return self.dev_type in (constants.LD_DRBD8, constants.LD_LV)
532 a8083063 Iustin Pop
533 a8083063 Iustin Pop
  def AssembleOnSecondary(self):
534 a8083063 Iustin Pop
    """Test if this device needs to be assembled on a secondary node."""
535 00fb8246 Michael Hanselmann
    return self.dev_type in (constants.LD_DRBD8, constants.LD_LV)
536 a8083063 Iustin Pop
537 a8083063 Iustin Pop
  def OpenOnSecondary(self):
538 a8083063 Iustin Pop
    """Test if this device needs to be opened on a secondary node."""
539 fe96220b Iustin Pop
    return self.dev_type in (constants.LD_LV,)
540 a8083063 Iustin Pop
541 222f2dd5 Iustin Pop
  def StaticDevPath(self):
542 222f2dd5 Iustin Pop
    """Return the device path if this device type has a static one.
543 222f2dd5 Iustin Pop

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

548 e51db2a6 Iustin Pop
    @warning: The path returned is not a normalized pathname; callers
549 e51db2a6 Iustin Pop
        should check that it is a valid path.
550 e51db2a6 Iustin Pop

551 222f2dd5 Iustin Pop
    """
552 222f2dd5 Iustin Pop
    if self.dev_type == constants.LD_LV:
553 222f2dd5 Iustin Pop
      return "/dev/%s/%s" % (self.logical_id[0], self.logical_id[1])
554 b6135bbc Apollon Oikonomopoulos
    elif self.dev_type == constants.LD_BLOCKDEV:
555 b6135bbc Apollon Oikonomopoulos
      return self.logical_id[1]
556 7181fba0 Constantinos Venetsanopoulos
    elif self.dev_type == constants.LD_RBD:
557 7181fba0 Constantinos Venetsanopoulos
      return "/dev/%s/%s" % (self.logical_id[0], self.logical_id[1])
558 222f2dd5 Iustin Pop
    return None
559 222f2dd5 Iustin Pop
560 fc1dc9d7 Iustin Pop
  def ChildrenNeeded(self):
561 fc1dc9d7 Iustin Pop
    """Compute the needed number of children for activation.
562 fc1dc9d7 Iustin Pop

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

567 fc1dc9d7 Iustin Pop
    Currently, only DRBD8 supports diskless activation (therefore we
568 fc1dc9d7 Iustin Pop
    return 0), for all other we keep the previous semantics and return
569 fc1dc9d7 Iustin Pop
    -1.
570 fc1dc9d7 Iustin Pop

571 fc1dc9d7 Iustin Pop
    """
572 fc1dc9d7 Iustin Pop
    if self.dev_type == constants.LD_DRBD8:
573 fc1dc9d7 Iustin Pop
      return 0
574 fc1dc9d7 Iustin Pop
    return -1
575 fc1dc9d7 Iustin Pop
576 51cb1581 Luca Bigliardi
  def IsBasedOnDiskType(self, dev_type):
577 51cb1581 Luca Bigliardi
    """Check if the disk or its children are based on the given type.
578 51cb1581 Luca Bigliardi

579 51cb1581 Luca Bigliardi
    @type dev_type: L{constants.LDS_BLOCK}
580 51cb1581 Luca Bigliardi
    @param dev_type: the type to look for
581 51cb1581 Luca Bigliardi
    @rtype: boolean
582 51cb1581 Luca Bigliardi
    @return: boolean indicating if a device of the given type was found or not
583 51cb1581 Luca Bigliardi

584 51cb1581 Luca Bigliardi
    """
585 51cb1581 Luca Bigliardi
    if self.children:
586 51cb1581 Luca Bigliardi
      for child in self.children:
587 51cb1581 Luca Bigliardi
        if child.IsBasedOnDiskType(dev_type):
588 51cb1581 Luca Bigliardi
          return True
589 51cb1581 Luca Bigliardi
    return self.dev_type == dev_type
590 51cb1581 Luca Bigliardi
591 a8083063 Iustin Pop
  def GetNodes(self, node):
592 a8083063 Iustin Pop
    """This function returns the nodes this device lives on.
593 a8083063 Iustin Pop

594 a8083063 Iustin Pop
    Given the node on which the parent of the device lives on (or, in
595 a8083063 Iustin Pop
    case of a top-level device, the primary node of the devices'
596 a8083063 Iustin Pop
    instance), this function will return a list of nodes on which this
597 a8083063 Iustin Pop
    devices needs to (or can) be assembled.
598 a8083063 Iustin Pop

599 a8083063 Iustin Pop
    """
600 b6135bbc Apollon Oikonomopoulos
    if self.dev_type in [constants.LD_LV, constants.LD_FILE,
601 7181fba0 Constantinos Venetsanopoulos
                         constants.LD_BLOCKDEV, constants.LD_RBD]:
602 a8083063 Iustin Pop
      result = [node]
603 a1f445d3 Iustin Pop
    elif self.dev_type in constants.LDS_DRBD:
604 a8083063 Iustin Pop
      result = [self.logical_id[0], self.logical_id[1]]
605 a8083063 Iustin Pop
      if node not in result:
606 3ecf6786 Iustin Pop
        raise errors.ConfigurationError("DRBD device passed unknown node")
607 a8083063 Iustin Pop
    else:
608 3ecf6786 Iustin Pop
      raise errors.ProgrammerError("Unhandled device type %s" % self.dev_type)
609 a8083063 Iustin Pop
    return result
610 a8083063 Iustin Pop
611 a8083063 Iustin Pop
  def ComputeNodeTree(self, parent_node):
612 a8083063 Iustin Pop
    """Compute the node/disk tree for this disk and its children.
613 a8083063 Iustin Pop

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

620 a8083063 Iustin Pop
    """
621 a8083063 Iustin Pop
    my_nodes = self.GetNodes(parent_node)
622 a8083063 Iustin Pop
    result = [(node, self) for node in my_nodes]
623 a8083063 Iustin Pop
    if not self.children:
624 a8083063 Iustin Pop
      # leaf device
625 a8083063 Iustin Pop
      return result
626 a8083063 Iustin Pop
    for node in my_nodes:
627 a8083063 Iustin Pop
      for child in self.children:
628 a8083063 Iustin Pop
        child_result = child.ComputeNodeTree(node)
629 a8083063 Iustin Pop
        if len(child_result) == 1:
630 a8083063 Iustin Pop
          # child (and all its descendants) is simple, doesn't split
631 a8083063 Iustin Pop
          # over multiple hosts, so we don't need to describe it, our
632 a8083063 Iustin Pop
          # own entry for this node describes it completely
633 a8083063 Iustin Pop
          continue
634 a8083063 Iustin Pop
        else:
635 a8083063 Iustin Pop
          # check if child nodes differ from my nodes; note that
636 a8083063 Iustin Pop
          # subdisk can differ from the child itself, and be instead
637 a8083063 Iustin Pop
          # one of its descendants
638 a8083063 Iustin Pop
          for subnode, subdisk in child_result:
639 a8083063 Iustin Pop
            if subnode not in my_nodes:
640 a8083063 Iustin Pop
              result.append((subnode, subdisk))
641 a8083063 Iustin Pop
            # otherwise child is under our own node, so we ignore this
642 a8083063 Iustin Pop
            # entry (but probably the other results in the list will
643 a8083063 Iustin Pop
            # be different)
644 a8083063 Iustin Pop
    return result
645 a8083063 Iustin Pop
646 6d33a6eb Iustin Pop
  def ComputeGrowth(self, amount):
647 6d33a6eb Iustin Pop
    """Compute the per-VG growth requirements.
648 6d33a6eb Iustin Pop

649 6d33a6eb Iustin Pop
    This only works for VG-based disks.
650 6d33a6eb Iustin Pop

651 6d33a6eb Iustin Pop
    @type amount: integer
652 6d33a6eb Iustin Pop
    @param amount: the desired increase in (user-visible) disk space
653 6d33a6eb Iustin Pop
    @rtype: dict
654 6d33a6eb Iustin Pop
    @return: a dictionary of volume-groups and the required size
655 6d33a6eb Iustin Pop

656 6d33a6eb Iustin Pop
    """
657 6d33a6eb Iustin Pop
    if self.dev_type == constants.LD_LV:
658 6d33a6eb Iustin Pop
      return {self.logical_id[0]: amount}
659 6d33a6eb Iustin Pop
    elif self.dev_type == constants.LD_DRBD8:
660 6d33a6eb Iustin Pop
      if self.children:
661 6d33a6eb Iustin Pop
        return self.children[0].ComputeGrowth(amount)
662 6d33a6eb Iustin Pop
      else:
663 6d33a6eb Iustin Pop
        return {}
664 6d33a6eb Iustin Pop
    else:
665 6d33a6eb Iustin Pop
      # Other disk types do not require VG space
666 6d33a6eb Iustin Pop
      return {}
667 6d33a6eb Iustin Pop
668 acec9d51 Iustin Pop
  def RecordGrow(self, amount):
669 acec9d51 Iustin Pop
    """Update the size of this disk after growth.
670 acec9d51 Iustin Pop

671 acec9d51 Iustin Pop
    This method recurses over the disks's children and updates their
672 acec9d51 Iustin Pop
    size correspondigly. The method needs to be kept in sync with the
673 acec9d51 Iustin Pop
    actual algorithms from bdev.
674 acec9d51 Iustin Pop

675 acec9d51 Iustin Pop
    """
676 7181fba0 Constantinos Venetsanopoulos
    if self.dev_type in (constants.LD_LV, constants.LD_FILE,
677 7181fba0 Constantinos Venetsanopoulos
                         constants.LD_RBD):
678 acec9d51 Iustin Pop
      self.size += amount
679 acec9d51 Iustin Pop
    elif self.dev_type == constants.LD_DRBD8:
680 acec9d51 Iustin Pop
      if self.children:
681 acec9d51 Iustin Pop
        self.children[0].RecordGrow(amount)
682 acec9d51 Iustin Pop
      self.size += amount
683 acec9d51 Iustin Pop
    else:
684 acec9d51 Iustin Pop
      raise errors.ProgrammerError("Disk.RecordGrow called for unsupported"
685 acec9d51 Iustin Pop
                                   " disk type %s" % self.dev_type)
686 acec9d51 Iustin Pop
687 735e1318 Michael Hanselmann
  def Update(self, size=None, mode=None):
688 735e1318 Michael Hanselmann
    """Apply changes to size and mode.
689 735e1318 Michael Hanselmann

690 735e1318 Michael Hanselmann
    """
691 735e1318 Michael Hanselmann
    if self.dev_type == constants.LD_DRBD8:
692 735e1318 Michael Hanselmann
      if self.children:
693 735e1318 Michael Hanselmann
        self.children[0].Update(size=size, mode=mode)
694 735e1318 Michael Hanselmann
    else:
695 735e1318 Michael Hanselmann
      assert not self.children
696 735e1318 Michael Hanselmann
697 735e1318 Michael Hanselmann
    if size is not None:
698 735e1318 Michael Hanselmann
      self.size = size
699 735e1318 Michael Hanselmann
    if mode is not None:
700 735e1318 Michael Hanselmann
      self.mode = mode
701 735e1318 Michael Hanselmann
702 a805ec18 Iustin Pop
  def UnsetSize(self):
703 a805ec18 Iustin Pop
    """Sets recursively the size to zero for the disk and its children.
704 a805ec18 Iustin Pop

705 a805ec18 Iustin Pop
    """
706 a805ec18 Iustin Pop
    if self.children:
707 a805ec18 Iustin Pop
      for child in self.children:
708 a805ec18 Iustin Pop
        child.UnsetSize()
709 a805ec18 Iustin Pop
    self.size = 0
710 a805ec18 Iustin Pop
711 0402302c Iustin Pop
  def SetPhysicalID(self, target_node, nodes_ip):
712 0402302c Iustin Pop
    """Convert the logical ID to the physical ID.
713 0402302c Iustin Pop

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

716 0402302c Iustin Pop
    The routine descends down and updates its children also, because
717 0402302c Iustin Pop
    this helps when the only the top device is passed to the remote
718 0402302c Iustin Pop
    node.
719 0402302c Iustin Pop

720 0402302c Iustin Pop
    Arguments:
721 0402302c Iustin Pop
      - target_node: the node we wish to configure for
722 0402302c Iustin Pop
      - nodes_ip: a mapping of node name to ip
723 0402302c Iustin Pop

724 0402302c Iustin Pop
    The target_node must exist in in nodes_ip, and must be one of the
725 0402302c Iustin Pop
    nodes in the logical ID for each of the DRBD devices encountered
726 0402302c Iustin Pop
    in the disk tree.
727 0402302c Iustin Pop

728 0402302c Iustin Pop
    """
729 0402302c Iustin Pop
    if self.children:
730 0402302c Iustin Pop
      for child in self.children:
731 0402302c Iustin Pop
        child.SetPhysicalID(target_node, nodes_ip)
732 0402302c Iustin Pop
733 0402302c Iustin Pop
    if self.logical_id is None and self.physical_id is not None:
734 0402302c Iustin Pop
      return
735 0402302c Iustin Pop
    if self.dev_type in constants.LDS_DRBD:
736 f9518d38 Iustin Pop
      pnode, snode, port, pminor, sminor, secret = self.logical_id
737 0402302c Iustin Pop
      if target_node not in (pnode, snode):
738 0402302c Iustin Pop
        raise errors.ConfigurationError("DRBD device not knowing node %s" %
739 0402302c Iustin Pop
                                        target_node)
740 0402302c Iustin Pop
      pnode_ip = nodes_ip.get(pnode, None)
741 0402302c Iustin Pop
      snode_ip = nodes_ip.get(snode, None)
742 0402302c Iustin Pop
      if pnode_ip is None or snode_ip is None:
743 0402302c Iustin Pop
        raise errors.ConfigurationError("Can't find primary or secondary node"
744 0402302c Iustin Pop
                                        " for %s" % str(self))
745 ffa1c0dc Iustin Pop
      p_data = (pnode_ip, port)
746 ffa1c0dc Iustin Pop
      s_data = (snode_ip, port)
747 0402302c Iustin Pop
      if pnode == target_node:
748 f9518d38 Iustin Pop
        self.physical_id = p_data + s_data + (pminor, secret)
749 0402302c Iustin Pop
      else: # it must be secondary, we tested above
750 f9518d38 Iustin Pop
        self.physical_id = s_data + p_data + (sminor, secret)
751 0402302c Iustin Pop
    else:
752 0402302c Iustin Pop
      self.physical_id = self.logical_id
753 0402302c Iustin Pop
    return
754 0402302c Iustin Pop
755 ff9c047c Iustin Pop
  def ToDict(self):
756 ff9c047c Iustin Pop
    """Disk-specific conversion to standard python types.
757 ff9c047c Iustin Pop

758 ff9c047c Iustin Pop
    This replaces the children lists of objects with lists of
759 ff9c047c Iustin Pop
    standard python types.
760 ff9c047c Iustin Pop

761 ff9c047c Iustin Pop
    """
762 ff9c047c Iustin Pop
    bo = super(Disk, self).ToDict()
763 ff9c047c Iustin Pop
764 ff9c047c Iustin Pop
    for attr in ("children",):
765 ff9c047c Iustin Pop
      alist = bo.get(attr, None)
766 ff9c047c Iustin Pop
      if alist:
767 ff9c047c Iustin Pop
        bo[attr] = self._ContainerToDicts(alist)
768 ff9c047c Iustin Pop
    return bo
769 ff9c047c Iustin Pop
770 ff9c047c Iustin Pop
  @classmethod
771 ff9c047c Iustin Pop
  def FromDict(cls, val):
772 ff9c047c Iustin Pop
    """Custom function for Disks
773 ff9c047c Iustin Pop

774 ff9c047c Iustin Pop
    """
775 ff9c047c Iustin Pop
    obj = super(Disk, cls).FromDict(val)
776 ff9c047c Iustin Pop
    if obj.children:
777 ff9c047c Iustin Pop
      obj.children = cls._ContainerFromDicts(obj.children, list, Disk)
778 ff9c047c Iustin Pop
    if obj.logical_id and isinstance(obj.logical_id, list):
779 ff9c047c Iustin Pop
      obj.logical_id = tuple(obj.logical_id)
780 ff9c047c Iustin Pop
    if obj.physical_id and isinstance(obj.physical_id, list):
781 ff9c047c Iustin Pop
      obj.physical_id = tuple(obj.physical_id)
782 f9518d38 Iustin Pop
    if obj.dev_type in constants.LDS_DRBD:
783 f9518d38 Iustin Pop
      # we need a tuple of length six here
784 f9518d38 Iustin Pop
      if len(obj.logical_id) < 6:
785 f9518d38 Iustin Pop
        obj.logical_id += (None,) * (6 - len(obj.logical_id))
786 ff9c047c Iustin Pop
    return obj
787 ff9c047c Iustin Pop
788 65a15336 Iustin Pop
  def __str__(self):
789 65a15336 Iustin Pop
    """Custom str() formatter for disks.
790 65a15336 Iustin Pop

791 65a15336 Iustin Pop
    """
792 65a15336 Iustin Pop
    if self.dev_type == constants.LD_LV:
793 e687ec01 Michael Hanselmann
      val = "<LogicalVolume(/dev/%s/%s" % self.logical_id
794 65a15336 Iustin Pop
    elif self.dev_type in constants.LDS_DRBD:
795 89f28b76 Iustin Pop
      node_a, node_b, port, minor_a, minor_b = self.logical_id[:5]
796 00fb8246 Michael Hanselmann
      val = "<DRBD8("
797 073ca59e Iustin Pop
      if self.physical_id is None:
798 073ca59e Iustin Pop
        phy = "unconfigured"
799 073ca59e Iustin Pop
      else:
800 073ca59e Iustin Pop
        phy = ("configured as %s:%s %s:%s" %
801 25a915d0 Iustin Pop
               (self.physical_id[0], self.physical_id[1],
802 25a915d0 Iustin Pop
                self.physical_id[2], self.physical_id[3]))
803 073ca59e Iustin Pop
804 89f28b76 Iustin Pop
      val += ("hosts=%s/%d-%s/%d, port=%s, %s, " %
805 89f28b76 Iustin Pop
              (node_a, minor_a, node_b, minor_b, port, phy))
806 65a15336 Iustin Pop
      if self.children and self.children.count(None) == 0:
807 65a15336 Iustin Pop
        val += "backend=%s, metadev=%s" % (self.children[0], self.children[1])
808 65a15336 Iustin Pop
      else:
809 65a15336 Iustin Pop
        val += "no local storage"
810 65a15336 Iustin Pop
    else:
811 65a15336 Iustin Pop
      val = ("<Disk(type=%s, logical_id=%s, physical_id=%s, children=%s" %
812 65a15336 Iustin Pop
             (self.dev_type, self.logical_id, self.physical_id, self.children))
813 65a15336 Iustin Pop
    if self.iv_name is None:
814 65a15336 Iustin Pop
      val += ", not visible"
815 65a15336 Iustin Pop
    else:
816 65a15336 Iustin Pop
      val += ", visible as /dev/%s" % self.iv_name
817 fd965830 Iustin Pop
    if isinstance(self.size, int):
818 fd965830 Iustin Pop
      val += ", size=%dm)>" % self.size
819 fd965830 Iustin Pop
    else:
820 fd965830 Iustin Pop
      val += ", size='%s')>" % (self.size,)
821 65a15336 Iustin Pop
    return val
822 65a15336 Iustin Pop
823 332d0e37 Iustin Pop
  def Verify(self):
824 332d0e37 Iustin Pop
    """Checks that this disk is correctly configured.
825 332d0e37 Iustin Pop

826 332d0e37 Iustin Pop
    """
827 7c4d6c7b Michael Hanselmann
    all_errors = []
828 332d0e37 Iustin Pop
    if self.mode not in constants.DISK_ACCESS_SET:
829 7c4d6c7b Michael Hanselmann
      all_errors.append("Disk access mode '%s' is invalid" % (self.mode, ))
830 7c4d6c7b Michael Hanselmann
    return all_errors
831 332d0e37 Iustin Pop
832 90d726a8 Iustin Pop
  def UpgradeConfig(self):
833 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
834 90d726a8 Iustin Pop

835 90d726a8 Iustin Pop
    """
836 90d726a8 Iustin Pop
    if self.children:
837 90d726a8 Iustin Pop
      for child in self.children:
838 90d726a8 Iustin Pop
        child.UpgradeConfig()
839 bc5d0215 Andrea Spadaccini
840 cce46164 René Nussbaumer
    # FIXME: Make this configurable in Ganeti 2.7
841 5dbee5ea Iustin Pop
    self.params = {}
842 90d726a8 Iustin Pop
    # add here config upgrade for this disk
843 90d726a8 Iustin Pop
844 cd46491f René Nussbaumer
  @staticmethod
845 cd46491f René Nussbaumer
  def ComputeLDParams(disk_template, disk_params):
846 cd46491f René Nussbaumer
    """Computes Logical Disk parameters from Disk Template parameters.
847 cd46491f René Nussbaumer

848 cd46491f René Nussbaumer
    @type disk_template: string
849 cd46491f René Nussbaumer
    @param disk_template: disk template, one of L{constants.DISK_TEMPLATES}
850 cd46491f René Nussbaumer
    @type disk_params: dict
851 cd46491f René Nussbaumer
    @param disk_params: disk template parameters;
852 cd46491f René Nussbaumer
                        dict(template_name -> parameters
853 cd46491f René Nussbaumer
    @rtype: list(dict)
854 cd46491f René Nussbaumer
    @return: a list of dicts, one for each node of the disk hierarchy. Each dict
855 cd46491f René Nussbaumer
      contains the LD parameters of the node. The tree is flattened in-order.
856 cd46491f René Nussbaumer

857 cd46491f René Nussbaumer
    """
858 cd46491f René Nussbaumer
    if disk_template not in constants.DISK_TEMPLATES:
859 cd46491f René Nussbaumer
      raise errors.ProgrammerError("Unknown disk template %s" % disk_template)
860 cd46491f René Nussbaumer
861 cd46491f René Nussbaumer
    assert disk_template in disk_params
862 cd46491f René Nussbaumer
863 cd46491f René Nussbaumer
    result = list()
864 cd46491f René Nussbaumer
    dt_params = disk_params[disk_template]
865 cd46491f René Nussbaumer
    if disk_template == constants.DT_DRBD8:
866 52f93ffd Michael Hanselmann
      result.append(FillDict(constants.DISK_LD_DEFAULTS[constants.LD_DRBD8], {
867 cd46491f René Nussbaumer
        constants.LDP_RESYNC_RATE: dt_params[constants.DRBD_RESYNC_RATE],
868 cd46491f René Nussbaumer
        constants.LDP_BARRIERS: dt_params[constants.DRBD_DISK_BARRIERS],
869 cd46491f René Nussbaumer
        constants.LDP_NO_META_FLUSH: dt_params[constants.DRBD_META_BARRIERS],
870 cd46491f René Nussbaumer
        constants.LDP_DEFAULT_METAVG: dt_params[constants.DRBD_DEFAULT_METAVG],
871 cd46491f René Nussbaumer
        constants.LDP_DISK_CUSTOM: dt_params[constants.DRBD_DISK_CUSTOM],
872 cd46491f René Nussbaumer
        constants.LDP_NET_CUSTOM: dt_params[constants.DRBD_NET_CUSTOM],
873 cd46491f René Nussbaumer
        constants.LDP_DYNAMIC_RESYNC: dt_params[constants.DRBD_DYNAMIC_RESYNC],
874 cd46491f René Nussbaumer
        constants.LDP_PLAN_AHEAD: dt_params[constants.DRBD_PLAN_AHEAD],
875 cd46491f René Nussbaumer
        constants.LDP_FILL_TARGET: dt_params[constants.DRBD_FILL_TARGET],
876 cd46491f René Nussbaumer
        constants.LDP_DELAY_TARGET: dt_params[constants.DRBD_DELAY_TARGET],
877 cd46491f René Nussbaumer
        constants.LDP_MAX_RATE: dt_params[constants.DRBD_MAX_RATE],
878 cd46491f René Nussbaumer
        constants.LDP_MIN_RATE: dt_params[constants.DRBD_MIN_RATE],
879 52f93ffd Michael Hanselmann
        }))
880 cd46491f René Nussbaumer
881 cd46491f René Nussbaumer
      # data LV
882 52f93ffd Michael Hanselmann
      result.append(FillDict(constants.DISK_LD_DEFAULTS[constants.LD_LV], {
883 cd46491f René Nussbaumer
        constants.LDP_STRIPES: dt_params[constants.DRBD_DATA_STRIPES],
884 52f93ffd Michael Hanselmann
        }))
885 cd46491f René Nussbaumer
886 cd46491f René Nussbaumer
      # metadata LV
887 52f93ffd Michael Hanselmann
      result.append(FillDict(constants.DISK_LD_DEFAULTS[constants.LD_LV], {
888 cd46491f René Nussbaumer
        constants.LDP_STRIPES: dt_params[constants.DRBD_META_STRIPES],
889 52f93ffd Michael Hanselmann
        }))
890 52f93ffd Michael Hanselmann
891 52f93ffd Michael Hanselmann
    elif disk_template in (constants.DT_FILE, constants.DT_SHARED_FILE):
892 cd46491f René Nussbaumer
      result.append(constants.DISK_LD_DEFAULTS[constants.LD_FILE])
893 cd46491f René Nussbaumer
894 cd46491f René Nussbaumer
    elif disk_template == constants.DT_PLAIN:
895 52f93ffd Michael Hanselmann
      result.append(FillDict(constants.DISK_LD_DEFAULTS[constants.LD_LV], {
896 cd46491f René Nussbaumer
        constants.LDP_STRIPES: dt_params[constants.LV_STRIPES],
897 52f93ffd Michael Hanselmann
        }))
898 cd46491f René Nussbaumer
899 cd46491f René Nussbaumer
    elif disk_template == constants.DT_BLOCK:
900 cd46491f René Nussbaumer
      result.append(constants.DISK_LD_DEFAULTS[constants.LD_BLOCKDEV])
901 cd46491f René Nussbaumer
902 cd46491f René Nussbaumer
    elif disk_template == constants.DT_RBD:
903 52f93ffd Michael Hanselmann
      result.append(FillDict(constants.DISK_LD_DEFAULTS[constants.LD_RBD], {
904 cd46491f René Nussbaumer
        constants.LDP_POOL: dt_params[constants.RBD_POOL]
905 52f93ffd Michael Hanselmann
        }))
906 cd46491f René Nussbaumer
907 cd46491f René Nussbaumer
    return result
908 cd46491f René Nussbaumer
909 a8083063 Iustin Pop
910 918eb80b Agata Murawska
class InstancePolicy(ConfigObject):
911 ffa339ca Iustin Pop
  """Config object representing instance policy limits dictionary.
912 918eb80b Agata Murawska

913 ffa339ca Iustin Pop

914 ffa339ca Iustin Pop
  Note that this object is not actually used in the config, it's just
915 ffa339ca Iustin Pop
  used as a placeholder for a few functions.
916 ffa339ca Iustin Pop

917 ffa339ca Iustin Pop
  """
918 918eb80b Agata Murawska
  @classmethod
919 8b057218 René Nussbaumer
  def CheckParameterSyntax(cls, ipolicy, check_std):
920 918eb80b Agata Murawska
    """ Check the instance policy for validity.
921 918eb80b Agata Murawska

922 918eb80b Agata Murawska
    """
923 918eb80b Agata Murawska
    for param in constants.ISPECS_PARAMETERS:
924 8b057218 René Nussbaumer
      InstancePolicy.CheckISpecSyntax(ipolicy, param, check_std)
925 d04c9d45 Iustin Pop
    if constants.IPOLICY_DTS in ipolicy:
926 d04c9d45 Iustin Pop
      InstancePolicy.CheckDiskTemplates(ipolicy[constants.IPOLICY_DTS])
927 ff6c5e55 Iustin Pop
    for key in constants.IPOLICY_PARAMETERS:
928 ff6c5e55 Iustin Pop
      if key in ipolicy:
929 ff6c5e55 Iustin Pop
        InstancePolicy.CheckParameter(key, ipolicy[key])
930 57dc299a Iustin Pop
    wrong_keys = frozenset(ipolicy.keys()) - constants.IPOLICY_ALL_KEYS
931 57dc299a Iustin Pop
    if wrong_keys:
932 57dc299a Iustin Pop
      raise errors.ConfigurationError("Invalid keys in ipolicy: %s" %
933 57dc299a Iustin Pop
                                      utils.CommaJoin(wrong_keys))
934 918eb80b Agata Murawska
935 918eb80b Agata Murawska
  @classmethod
936 8b057218 René Nussbaumer
  def CheckISpecSyntax(cls, ipolicy, name, check_std):
937 918eb80b Agata Murawska
    """Check the instance policy for validity on a given key.
938 918eb80b Agata Murawska

939 918eb80b Agata Murawska
    We check if the instance policy makes sense for a given key, that is
940 918eb80b Agata Murawska
    if ipolicy[min][name] <= ipolicy[std][name] <= ipolicy[max][name].
941 918eb80b Agata Murawska

942 918eb80b Agata Murawska
    @type ipolicy: dict
943 918eb80b Agata Murawska
    @param ipolicy: dictionary with min, max, std specs
944 918eb80b Agata Murawska
    @type name: string
945 918eb80b Agata Murawska
    @param name: what are the limits for
946 8b057218 René Nussbaumer
    @type check_std: bool
947 8b057218 René Nussbaumer
    @param check_std: Whether to check std value or just assume compliance
948 918eb80b Agata Murawska
    @raise errors.ConfigureError: when specs for given name are not valid
949 918eb80b Agata Murawska

950 918eb80b Agata Murawska
    """
951 4f725341 Agata Murawska
    min_v = ipolicy[constants.ISPECS_MIN].get(name, 0)
952 8b057218 René Nussbaumer
953 8b057218 René Nussbaumer
    if check_std:
954 8b057218 René Nussbaumer
      std_v = ipolicy[constants.ISPECS_STD].get(name, min_v)
955 8b057218 René Nussbaumer
      std_msg = std_v
956 8b057218 René Nussbaumer
    else:
957 8b057218 René Nussbaumer
      std_v = min_v
958 8b057218 René Nussbaumer
      std_msg = "-"
959 8b057218 René Nussbaumer
960 4f725341 Agata Murawska
    max_v = ipolicy[constants.ISPECS_MAX].get(name, std_v)
961 918eb80b Agata Murawska
    err = ("Invalid specification of min/max/std values for %s: %s/%s/%s" %
962 918eb80b Agata Murawska
           (name,
963 4f725341 Agata Murawska
            ipolicy[constants.ISPECS_MIN].get(name, "-"),
964 4f725341 Agata Murawska
            ipolicy[constants.ISPECS_MAX].get(name, "-"),
965 8b057218 René Nussbaumer
            std_msg))
966 918eb80b Agata Murawska
    if min_v > std_v or std_v > max_v:
967 918eb80b Agata Murawska
      raise errors.ConfigurationError(err)
968 918eb80b Agata Murawska
969 2cc673a3 Iustin Pop
  @classmethod
970 2cc673a3 Iustin Pop
  def CheckDiskTemplates(cls, disk_templates):
971 2cc673a3 Iustin Pop
    """Checks the disk templates for validity.
972 2cc673a3 Iustin Pop

973 2cc673a3 Iustin Pop
    """
974 2cc673a3 Iustin Pop
    wrong = frozenset(disk_templates).difference(constants.DISK_TEMPLATES)
975 2cc673a3 Iustin Pop
    if wrong:
976 2cc673a3 Iustin Pop
      raise errors.ConfigurationError("Invalid disk template(s) %s" %
977 2cc673a3 Iustin Pop
                                      utils.CommaJoin(wrong))
978 2cc673a3 Iustin Pop
979 ff6c5e55 Iustin Pop
  @classmethod
980 ff6c5e55 Iustin Pop
  def CheckParameter(cls, key, value):
981 ff6c5e55 Iustin Pop
    """Checks a parameter.
982 ff6c5e55 Iustin Pop

983 ff6c5e55 Iustin Pop
    Currently we expect all parameters to be float values.
984 ff6c5e55 Iustin Pop

985 ff6c5e55 Iustin Pop
    """
986 ff6c5e55 Iustin Pop
    try:
987 ff6c5e55 Iustin Pop
      float(value)
988 ff6c5e55 Iustin Pop
    except (TypeError, ValueError), err:
989 ff6c5e55 Iustin Pop
      raise errors.ConfigurationError("Invalid value for key" " '%s':"
990 ff6c5e55 Iustin Pop
                                      " '%s', error: %s" % (key, value, err))
991 ff6c5e55 Iustin Pop
992 918eb80b Agata Murawska
993 ec29fe40 Iustin Pop
class Instance(TaggableObject):
994 a8083063 Iustin Pop
  """Config object representing an instance."""
995 154b9580 Balazs Lecz
  __slots__ = [
996 a8083063 Iustin Pop
    "name",
997 a8083063 Iustin Pop
    "primary_node",
998 a8083063 Iustin Pop
    "os",
999 e69d05fd Iustin Pop
    "hypervisor",
1000 5bf7b5cf Iustin Pop
    "hvparams",
1001 5bf7b5cf Iustin Pop
    "beparams",
1002 1bdcbbab Iustin Pop
    "osparams",
1003 9ca8a7c5 Agata Murawska
    "admin_state",
1004 a8083063 Iustin Pop
    "nics",
1005 a8083063 Iustin Pop
    "disks",
1006 a8083063 Iustin Pop
    "disk_template",
1007 58acb49d Alexander Schreiber
    "network_port",
1008 be1fa613 Iustin Pop
    "serial_no",
1009 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
1010 a8083063 Iustin Pop
1011 a8083063 Iustin Pop
  def _ComputeSecondaryNodes(self):
1012 a8083063 Iustin Pop
    """Compute the list of secondary nodes.
1013 a8083063 Iustin Pop

1014 cfcc5c6d Iustin Pop
    This is a simple wrapper over _ComputeAllNodes.
1015 cfcc5c6d Iustin Pop

1016 cfcc5c6d Iustin Pop
    """
1017 cfcc5c6d Iustin Pop
    all_nodes = set(self._ComputeAllNodes())
1018 cfcc5c6d Iustin Pop
    all_nodes.discard(self.primary_node)
1019 cfcc5c6d Iustin Pop
    return tuple(all_nodes)
1020 cfcc5c6d Iustin Pop
1021 cfcc5c6d Iustin Pop
  secondary_nodes = property(_ComputeSecondaryNodes, None, None,
1022 cfcc5c6d Iustin Pop
                             "List of secondary nodes")
1023 cfcc5c6d Iustin Pop
1024 cfcc5c6d Iustin Pop
  def _ComputeAllNodes(self):
1025 cfcc5c6d Iustin Pop
    """Compute the list of all nodes.
1026 cfcc5c6d Iustin Pop

1027 a8083063 Iustin Pop
    Since the data is already there (in the drbd disks), keeping it as
1028 a8083063 Iustin Pop
    a separate normal attribute is redundant and if not properly
1029 a8083063 Iustin Pop
    synchronised can cause problems. Thus it's better to compute it
1030 a8083063 Iustin Pop
    dynamically.
1031 a8083063 Iustin Pop

1032 a8083063 Iustin Pop
    """
1033 cfcc5c6d Iustin Pop
    def _Helper(nodes, device):
1034 cfcc5c6d Iustin Pop
      """Recursively computes nodes given a top device."""
1035 a1f445d3 Iustin Pop
      if device.dev_type in constants.LDS_DRBD:
1036 cfcc5c6d Iustin Pop
        nodea, nodeb = device.logical_id[:2]
1037 cfcc5c6d Iustin Pop
        nodes.add(nodea)
1038 cfcc5c6d Iustin Pop
        nodes.add(nodeb)
1039 a8083063 Iustin Pop
      if device.children:
1040 a8083063 Iustin Pop
        for child in device.children:
1041 cfcc5c6d Iustin Pop
          _Helper(nodes, child)
1042 a8083063 Iustin Pop
1043 cfcc5c6d Iustin Pop
    all_nodes = set()
1044 99c7b2a1 Iustin Pop
    all_nodes.add(self.primary_node)
1045 a8083063 Iustin Pop
    for device in self.disks:
1046 cfcc5c6d Iustin Pop
      _Helper(all_nodes, device)
1047 cfcc5c6d Iustin Pop
    return tuple(all_nodes)
1048 a8083063 Iustin Pop
1049 cfcc5c6d Iustin Pop
  all_nodes = property(_ComputeAllNodes, None, None,
1050 cfcc5c6d Iustin Pop
                       "List of all nodes of the instance")
1051 a8083063 Iustin Pop
1052 a8083063 Iustin Pop
  def MapLVsByNode(self, lvmap=None, devs=None, node=None):
1053 a8083063 Iustin Pop
    """Provide a mapping of nodes to LVs this instance owns.
1054 a8083063 Iustin Pop

1055 c41eea6e Iustin Pop
    This function figures out what logical volumes should belong on
1056 c41eea6e Iustin Pop
    which nodes, recursing through a device tree.
1057 a8083063 Iustin Pop

1058 c41eea6e Iustin Pop
    @param lvmap: optional dictionary to receive the
1059 c41eea6e Iustin Pop
        'node' : ['lv', ...] data.
1060 a8083063 Iustin Pop

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

1066 a8083063 Iustin Pop
    """
1067 5ae4945a Iustin Pop
    if node is None:
1068 a8083063 Iustin Pop
      node = self.primary_node
1069 a8083063 Iustin Pop
1070 a8083063 Iustin Pop
    if lvmap is None:
1071 e687ec01 Michael Hanselmann
      lvmap = {
1072 e687ec01 Michael Hanselmann
        node: [],
1073 e687ec01 Michael Hanselmann
        }
1074 a8083063 Iustin Pop
      ret = lvmap
1075 a8083063 Iustin Pop
    else:
1076 a8083063 Iustin Pop
      if not node in lvmap:
1077 a8083063 Iustin Pop
        lvmap[node] = []
1078 a8083063 Iustin Pop
      ret = None
1079 a8083063 Iustin Pop
1080 a8083063 Iustin Pop
    if not devs:
1081 a8083063 Iustin Pop
      devs = self.disks
1082 a8083063 Iustin Pop
1083 a8083063 Iustin Pop
    for dev in devs:
1084 fe96220b Iustin Pop
      if dev.dev_type == constants.LD_LV:
1085 e687ec01 Michael Hanselmann
        lvmap[node].append(dev.logical_id[0] + "/" + dev.logical_id[1])
1086 a8083063 Iustin Pop
1087 a1f445d3 Iustin Pop
      elif dev.dev_type in constants.LDS_DRBD:
1088 a8083063 Iustin Pop
        if dev.children:
1089 a8083063 Iustin Pop
          self.MapLVsByNode(lvmap, dev.children, dev.logical_id[0])
1090 a8083063 Iustin Pop
          self.MapLVsByNode(lvmap, dev.children, dev.logical_id[1])
1091 a8083063 Iustin Pop
1092 a8083063 Iustin Pop
      elif dev.children:
1093 a8083063 Iustin Pop
        self.MapLVsByNode(lvmap, dev.children, node)
1094 a8083063 Iustin Pop
1095 a8083063 Iustin Pop
    return ret
1096 a8083063 Iustin Pop
1097 ad24e046 Iustin Pop
  def FindDisk(self, idx):
1098 ad24e046 Iustin Pop
    """Find a disk given having a specified index.
1099 644eeef9 Iustin Pop

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

1102 ad24e046 Iustin Pop
    @type idx: int
1103 ad24e046 Iustin Pop
    @param idx: the disk index
1104 ad24e046 Iustin Pop
    @rtype: L{Disk}
1105 ad24e046 Iustin Pop
    @return: the corresponding disk
1106 ad24e046 Iustin Pop
    @raise errors.OpPrereqError: when the given index is not valid
1107 644eeef9 Iustin Pop

1108 ad24e046 Iustin Pop
    """
1109 ad24e046 Iustin Pop
    try:
1110 ad24e046 Iustin Pop
      idx = int(idx)
1111 ad24e046 Iustin Pop
      return self.disks[idx]
1112 691744c4 Iustin Pop
    except (TypeError, ValueError), err:
1113 debac808 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index: '%s'" % str(err),
1114 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
1115 ad24e046 Iustin Pop
    except IndexError:
1116 ad24e046 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index: %d (instace has disks"
1117 daa55b04 Michael Hanselmann
                                 " 0 to %d" % (idx, len(self.disks) - 1),
1118 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
1119 644eeef9 Iustin Pop
1120 ff9c047c Iustin Pop
  def ToDict(self):
1121 ff9c047c Iustin Pop
    """Instance-specific conversion to standard python types.
1122 ff9c047c Iustin Pop

1123 ff9c047c Iustin Pop
    This replaces the children lists of objects with lists of standard
1124 ff9c047c Iustin Pop
    python types.
1125 ff9c047c Iustin Pop

1126 ff9c047c Iustin Pop
    """
1127 ff9c047c Iustin Pop
    bo = super(Instance, self).ToDict()
1128 ff9c047c Iustin Pop
1129 ff9c047c Iustin Pop
    for attr in "nics", "disks":
1130 ff9c047c Iustin Pop
      alist = bo.get(attr, None)
1131 ff9c047c Iustin Pop
      if alist:
1132 ff9c047c Iustin Pop
        nlist = self._ContainerToDicts(alist)
1133 ff9c047c Iustin Pop
      else:
1134 ff9c047c Iustin Pop
        nlist = []
1135 ff9c047c Iustin Pop
      bo[attr] = nlist
1136 ff9c047c Iustin Pop
    return bo
1137 ff9c047c Iustin Pop
1138 ff9c047c Iustin Pop
  @classmethod
1139 ff9c047c Iustin Pop
  def FromDict(cls, val):
1140 ff9c047c Iustin Pop
    """Custom function for instances.
1141 ff9c047c Iustin Pop

1142 ff9c047c Iustin Pop
    """
1143 9ca8a7c5 Agata Murawska
    if "admin_state" not in val:
1144 9ca8a7c5 Agata Murawska
      if val.get("admin_up", False):
1145 9ca8a7c5 Agata Murawska
        val["admin_state"] = constants.ADMINST_UP
1146 9ca8a7c5 Agata Murawska
      else:
1147 9ca8a7c5 Agata Murawska
        val["admin_state"] = constants.ADMINST_DOWN
1148 9ca8a7c5 Agata Murawska
    if "admin_up" in val:
1149 9ca8a7c5 Agata Murawska
      del val["admin_up"]
1150 ff9c047c Iustin Pop
    obj = super(Instance, cls).FromDict(val)
1151 ff9c047c Iustin Pop
    obj.nics = cls._ContainerFromDicts(obj.nics, list, NIC)
1152 ff9c047c Iustin Pop
    obj.disks = cls._ContainerFromDicts(obj.disks, list, Disk)
1153 ff9c047c Iustin Pop
    return obj
1154 ff9c047c Iustin Pop
1155 90d726a8 Iustin Pop
  def UpgradeConfig(self):
1156 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
1157 90d726a8 Iustin Pop

1158 90d726a8 Iustin Pop
    """
1159 90d726a8 Iustin Pop
    for nic in self.nics:
1160 90d726a8 Iustin Pop
      nic.UpgradeConfig()
1161 90d726a8 Iustin Pop
    for disk in self.disks:
1162 90d726a8 Iustin Pop
      disk.UpgradeConfig()
1163 7736a5f2 Iustin Pop
    if self.hvparams:
1164 7736a5f2 Iustin Pop
      for key in constants.HVC_GLOBALS:
1165 7736a5f2 Iustin Pop
        try:
1166 7736a5f2 Iustin Pop
          del self.hvparams[key]
1167 7736a5f2 Iustin Pop
        except KeyError:
1168 7736a5f2 Iustin Pop
          pass
1169 1bdcbbab Iustin Pop
    if self.osparams is None:
1170 1bdcbbab Iustin Pop
      self.osparams = {}
1171 8c72ab2b Guido Trotter
    UpgradeBeParams(self.beparams)
1172 90d726a8 Iustin Pop
1173 a8083063 Iustin Pop
1174 a8083063 Iustin Pop
class OS(ConfigObject):
1175 b41b3516 Iustin Pop
  """Config object representing an operating system.
1176 b41b3516 Iustin Pop

1177 b41b3516 Iustin Pop
  @type supported_parameters: list
1178 b41b3516 Iustin Pop
  @ivar supported_parameters: a list of tuples, name and description,
1179 b41b3516 Iustin Pop
      containing the supported parameters by this OS
1180 b41b3516 Iustin Pop

1181 870dc44c Iustin Pop
  @type VARIANT_DELIM: string
1182 870dc44c Iustin Pop
  @cvar VARIANT_DELIM: the variant delimiter
1183 870dc44c Iustin Pop

1184 b41b3516 Iustin Pop
  """
1185 a8083063 Iustin Pop
  __slots__ = [
1186 a8083063 Iustin Pop
    "name",
1187 a8083063 Iustin Pop
    "path",
1188 082a7f91 Guido Trotter
    "api_versions",
1189 a8083063 Iustin Pop
    "create_script",
1190 a8083063 Iustin Pop
    "export_script",
1191 386b57af Iustin Pop
    "import_script",
1192 386b57af Iustin Pop
    "rename_script",
1193 b41b3516 Iustin Pop
    "verify_script",
1194 6d79896b Guido Trotter
    "supported_variants",
1195 b41b3516 Iustin Pop
    "supported_parameters",
1196 a8083063 Iustin Pop
    ]
1197 a8083063 Iustin Pop
1198 870dc44c Iustin Pop
  VARIANT_DELIM = "+"
1199 870dc44c Iustin Pop
1200 870dc44c Iustin Pop
  @classmethod
1201 870dc44c Iustin Pop
  def SplitNameVariant(cls, name):
1202 870dc44c Iustin Pop
    """Splits the name into the proper name and variant.
1203 870dc44c Iustin Pop

1204 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
1205 870dc44c Iustin Pop
    @rtype: list
1206 870dc44c Iustin Pop
    @return: a list of two elements; if the original name didn't
1207 870dc44c Iustin Pop
        contain a variant, it's returned as an empty string
1208 870dc44c Iustin Pop

1209 870dc44c Iustin Pop
    """
1210 870dc44c Iustin Pop
    nv = name.split(cls.VARIANT_DELIM, 1)
1211 870dc44c Iustin Pop
    if len(nv) == 1:
1212 870dc44c Iustin Pop
      nv.append("")
1213 870dc44c Iustin Pop
    return nv
1214 870dc44c Iustin Pop
1215 870dc44c Iustin Pop
  @classmethod
1216 870dc44c Iustin Pop
  def GetName(cls, name):
1217 870dc44c Iustin Pop
    """Returns the proper name of the os (without the variant).
1218 870dc44c Iustin Pop

1219 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
1220 870dc44c Iustin Pop

1221 870dc44c Iustin Pop
    """
1222 870dc44c Iustin Pop
    return cls.SplitNameVariant(name)[0]
1223 870dc44c Iustin Pop
1224 870dc44c Iustin Pop
  @classmethod
1225 870dc44c Iustin Pop
  def GetVariant(cls, name):
1226 870dc44c Iustin Pop
    """Returns the variant the os (without the base name).
1227 870dc44c Iustin Pop

1228 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
1229 870dc44c Iustin Pop

1230 870dc44c Iustin Pop
    """
1231 870dc44c Iustin Pop
    return cls.SplitNameVariant(name)[1]
1232 870dc44c Iustin Pop
1233 7c0d6283 Michael Hanselmann
1234 5f06ce5e Michael Hanselmann
class NodeHvState(ConfigObject):
1235 5f06ce5e Michael Hanselmann
  """Hypvervisor state on a node.
1236 5f06ce5e Michael Hanselmann

1237 5f06ce5e Michael Hanselmann
  @ivar mem_total: Total amount of memory
1238 5f06ce5e Michael Hanselmann
  @ivar mem_node: Memory used by, or reserved for, the node itself (not always
1239 5f06ce5e Michael Hanselmann
    available)
1240 5f06ce5e Michael Hanselmann
  @ivar mem_hv: Memory used by hypervisor or lost due to instance allocation
1241 5f06ce5e Michael Hanselmann
    rounding
1242 5f06ce5e Michael Hanselmann
  @ivar mem_inst: Memory used by instances living on node
1243 5f06ce5e Michael Hanselmann
  @ivar cpu_total: Total node CPU core count
1244 5f06ce5e Michael Hanselmann
  @ivar cpu_node: Number of CPU cores reserved for the node itself
1245 5f06ce5e Michael Hanselmann

1246 5f06ce5e Michael Hanselmann
  """
1247 5f06ce5e Michael Hanselmann
  __slots__ = [
1248 5f06ce5e Michael Hanselmann
    "mem_total",
1249 5f06ce5e Michael Hanselmann
    "mem_node",
1250 5f06ce5e Michael Hanselmann
    "mem_hv",
1251 5f06ce5e Michael Hanselmann
    "mem_inst",
1252 5f06ce5e Michael Hanselmann
    "cpu_total",
1253 5f06ce5e Michael Hanselmann
    "cpu_node",
1254 5f06ce5e Michael Hanselmann
    ] + _TIMESTAMPS
1255 5f06ce5e Michael Hanselmann
1256 5f06ce5e Michael Hanselmann
1257 5f06ce5e Michael Hanselmann
class NodeDiskState(ConfigObject):
1258 5f06ce5e Michael Hanselmann
  """Disk state on a node.
1259 5f06ce5e Michael Hanselmann

1260 5f06ce5e Michael Hanselmann
  """
1261 5f06ce5e Michael Hanselmann
  __slots__ = [
1262 5f06ce5e Michael Hanselmann
    "total",
1263 5f06ce5e Michael Hanselmann
    "reserved",
1264 5f06ce5e Michael Hanselmann
    "overhead",
1265 5f06ce5e Michael Hanselmann
    ] + _TIMESTAMPS
1266 5f06ce5e Michael Hanselmann
1267 5f06ce5e Michael Hanselmann
1268 ec29fe40 Iustin Pop
class Node(TaggableObject):
1269 634d30f4 Michael Hanselmann
  """Config object representing a node.
1270 634d30f4 Michael Hanselmann

1271 634d30f4 Michael Hanselmann
  @ivar hv_state: Hypervisor state (e.g. number of CPUs)
1272 634d30f4 Michael Hanselmann
  @ivar hv_state_static: Hypervisor state overriden by user
1273 634d30f4 Michael Hanselmann
  @ivar disk_state: Disk state (e.g. free space)
1274 634d30f4 Michael Hanselmann
  @ivar disk_state_static: Disk state overriden by user
1275 634d30f4 Michael Hanselmann

1276 634d30f4 Michael Hanselmann
  """
1277 154b9580 Balazs Lecz
  __slots__ = [
1278 ec29fe40 Iustin Pop
    "name",
1279 ec29fe40 Iustin Pop
    "primary_ip",
1280 ec29fe40 Iustin Pop
    "secondary_ip",
1281 be1fa613 Iustin Pop
    "serial_no",
1282 8b8b8b81 Iustin Pop
    "master_candidate",
1283 fc0fe88c Iustin Pop
    "offline",
1284 af64c0ea Iustin Pop
    "drained",
1285 f936c153 Iustin Pop
    "group",
1286 490acd18 Iustin Pop
    "master_capable",
1287 490acd18 Iustin Pop
    "vm_capable",
1288 095e71aa René Nussbaumer
    "ndparams",
1289 25124d4a René Nussbaumer
    "powered",
1290 5b49ed09 René Nussbaumer
    "hv_state",
1291 634d30f4 Michael Hanselmann
    "hv_state_static",
1292 5b49ed09 René Nussbaumer
    "disk_state",
1293 634d30f4 Michael Hanselmann
    "disk_state_static",
1294 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
1295 a8083063 Iustin Pop
1296 490acd18 Iustin Pop
  def UpgradeConfig(self):
1297 490acd18 Iustin Pop
    """Fill defaults for missing configuration values.
1298 490acd18 Iustin Pop

1299 490acd18 Iustin Pop
    """
1300 b459a848 Andrea Spadaccini
    # pylint: disable=E0203
1301 490acd18 Iustin Pop
    # because these are "defined" via slots, not manually
1302 490acd18 Iustin Pop
    if self.master_capable is None:
1303 490acd18 Iustin Pop
      self.master_capable = True
1304 490acd18 Iustin Pop
1305 490acd18 Iustin Pop
    if self.vm_capable is None:
1306 490acd18 Iustin Pop
      self.vm_capable = True
1307 490acd18 Iustin Pop
1308 095e71aa René Nussbaumer
    if self.ndparams is None:
1309 095e71aa René Nussbaumer
      self.ndparams = {}
1310 095e71aa René Nussbaumer
1311 25124d4a René Nussbaumer
    if self.powered is None:
1312 25124d4a René Nussbaumer
      self.powered = True
1313 25124d4a René Nussbaumer
1314 5f06ce5e Michael Hanselmann
  def ToDict(self):
1315 5f06ce5e Michael Hanselmann
    """Custom function for serializing.
1316 5f06ce5e Michael Hanselmann

1317 5f06ce5e Michael Hanselmann
    """
1318 5f06ce5e Michael Hanselmann
    data = super(Node, self).ToDict()
1319 5f06ce5e Michael Hanselmann
1320 5f06ce5e Michael Hanselmann
    hv_state = data.get("hv_state", None)
1321 5f06ce5e Michael Hanselmann
    if hv_state is not None:
1322 5f06ce5e Michael Hanselmann
      data["hv_state"] = self._ContainerToDicts(hv_state)
1323 5f06ce5e Michael Hanselmann
1324 5f06ce5e Michael Hanselmann
    disk_state = data.get("disk_state", None)
1325 5f06ce5e Michael Hanselmann
    if disk_state is not None:
1326 5f06ce5e Michael Hanselmann
      data["disk_state"] = \
1327 5f06ce5e Michael Hanselmann
        dict((key, self._ContainerToDicts(value))
1328 5f06ce5e Michael Hanselmann
             for (key, value) in disk_state.items())
1329 5f06ce5e Michael Hanselmann
1330 5f06ce5e Michael Hanselmann
    return data
1331 5f06ce5e Michael Hanselmann
1332 5f06ce5e Michael Hanselmann
  @classmethod
1333 5f06ce5e Michael Hanselmann
  def FromDict(cls, val):
1334 5f06ce5e Michael Hanselmann
    """Custom function for deserializing.
1335 5f06ce5e Michael Hanselmann

1336 5f06ce5e Michael Hanselmann
    """
1337 5f06ce5e Michael Hanselmann
    obj = super(Node, cls).FromDict(val)
1338 5f06ce5e Michael Hanselmann
1339 5f06ce5e Michael Hanselmann
    if obj.hv_state is not None:
1340 5f06ce5e Michael Hanselmann
      obj.hv_state = cls._ContainerFromDicts(obj.hv_state, dict, NodeHvState)
1341 5f06ce5e Michael Hanselmann
1342 5f06ce5e Michael Hanselmann
    if obj.disk_state is not None:
1343 5f06ce5e Michael Hanselmann
      obj.disk_state = \
1344 5f06ce5e Michael Hanselmann
        dict((key, cls._ContainerFromDicts(value, dict, NodeDiskState))
1345 5f06ce5e Michael Hanselmann
             for (key, value) in obj.disk_state.items())
1346 5f06ce5e Michael Hanselmann
1347 5f06ce5e Michael Hanselmann
    return obj
1348 5f06ce5e Michael Hanselmann
1349 a8083063 Iustin Pop
1350 1ffd2673 Michael Hanselmann
class NodeGroup(TaggableObject):
1351 24a3707f Guido Trotter
  """Config object representing a node group."""
1352 24a3707f Guido Trotter
  __slots__ = [
1353 24a3707f Guido Trotter
    "name",
1354 24a3707f Guido Trotter
    "members",
1355 095e71aa René Nussbaumer
    "ndparams",
1356 bc5d0215 Andrea Spadaccini
    "diskparams",
1357 81e3ab4f Agata Murawska
    "ipolicy",
1358 e11a1b77 Adeodato Simo
    "serial_no",
1359 a8282327 René Nussbaumer
    "hv_state_static",
1360 a8282327 René Nussbaumer
    "disk_state_static",
1361 90e99856 Adeodato Simo
    "alloc_policy",
1362 24a3707f Guido Trotter
    ] + _TIMESTAMPS + _UUID
1363 24a3707f Guido Trotter
1364 24a3707f Guido Trotter
  def ToDict(self):
1365 24a3707f Guido Trotter
    """Custom function for nodegroup.
1366 24a3707f Guido Trotter

1367 c60abd62 Guido Trotter
    This discards the members object, which gets recalculated and is only kept
1368 c60abd62 Guido Trotter
    in memory.
1369 24a3707f Guido Trotter

1370 24a3707f Guido Trotter
    """
1371 24a3707f Guido Trotter
    mydict = super(NodeGroup, self).ToDict()
1372 24a3707f Guido Trotter
    del mydict["members"]
1373 24a3707f Guido Trotter
    return mydict
1374 24a3707f Guido Trotter
1375 24a3707f Guido Trotter
  @classmethod
1376 24a3707f Guido Trotter
  def FromDict(cls, val):
1377 24a3707f Guido Trotter
    """Custom function for nodegroup.
1378 24a3707f Guido Trotter

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

1381 24a3707f Guido Trotter
    """
1382 24a3707f Guido Trotter
    obj = super(NodeGroup, cls).FromDict(val)
1383 24a3707f Guido Trotter
    obj.members = []
1384 24a3707f Guido Trotter
    return obj
1385 24a3707f Guido Trotter
1386 095e71aa René Nussbaumer
  def UpgradeConfig(self):
1387 095e71aa René Nussbaumer
    """Fill defaults for missing configuration values.
1388 095e71aa René Nussbaumer

1389 095e71aa René Nussbaumer
    """
1390 095e71aa René Nussbaumer
    if self.ndparams is None:
1391 095e71aa René Nussbaumer
      self.ndparams = {}
1392 095e71aa René Nussbaumer
1393 e11a1b77 Adeodato Simo
    if self.serial_no is None:
1394 e11a1b77 Adeodato Simo
      self.serial_no = 1
1395 e11a1b77 Adeodato Simo
1396 90e99856 Adeodato Simo
    if self.alloc_policy is None:
1397 90e99856 Adeodato Simo
      self.alloc_policy = constants.ALLOC_POLICY_PREFERRED
1398 90e99856 Adeodato Simo
1399 4b97458c Iustin Pop
    # We only update mtime, and not ctime, since we would not be able
1400 4b97458c Iustin Pop
    # to provide a correct value for creation time.
1401 e11a1b77 Adeodato Simo
    if self.mtime is None:
1402 e11a1b77 Adeodato Simo
      self.mtime = time.time()
1403 e11a1b77 Adeodato Simo
1404 7228ca91 René Nussbaumer
    if self.diskparams is None:
1405 7228ca91 René Nussbaumer
      self.diskparams = {}
1406 81e3ab4f Agata Murawska
    if self.ipolicy is None:
1407 81e3ab4f Agata Murawska
      self.ipolicy = MakeEmptyIPolicy()
1408 bc5d0215 Andrea Spadaccini
1409 095e71aa René Nussbaumer
  def FillND(self, node):
1410 ce523de1 Michael Hanselmann
    """Return filled out ndparams for L{objects.Node}
1411 095e71aa René Nussbaumer

1412 095e71aa René Nussbaumer
    @type node: L{objects.Node}
1413 095e71aa René Nussbaumer
    @param node: A Node object to fill
1414 095e71aa René Nussbaumer
    @return a copy of the node's ndparams with defaults filled
1415 095e71aa René Nussbaumer

1416 095e71aa René Nussbaumer
    """
1417 095e71aa René Nussbaumer
    return self.SimpleFillND(node.ndparams)
1418 095e71aa René Nussbaumer
1419 095e71aa René Nussbaumer
  def SimpleFillND(self, ndparams):
1420 095e71aa René Nussbaumer
    """Fill a given ndparams dict with defaults.
1421 095e71aa René Nussbaumer

1422 095e71aa René Nussbaumer
    @type ndparams: dict
1423 095e71aa René Nussbaumer
    @param ndparams: the dict to fill
1424 095e71aa René Nussbaumer
    @rtype: dict
1425 095e71aa René Nussbaumer
    @return: a copy of the passed in ndparams with missing keys filled
1426 e6e88de6 Adeodato Simo
        from the node group defaults
1427 095e71aa René Nussbaumer

1428 095e71aa René Nussbaumer
    """
1429 095e71aa René Nussbaumer
    return FillDict(self.ndparams, ndparams)
1430 095e71aa René Nussbaumer
1431 24a3707f Guido Trotter
1432 ec29fe40 Iustin Pop
class Cluster(TaggableObject):
1433 a8083063 Iustin Pop
  """Config object representing the cluster."""
1434 154b9580 Balazs Lecz
  __slots__ = [
1435 a8083063 Iustin Pop
    "serial_no",
1436 a8083063 Iustin Pop
    "rsahostkeypub",
1437 a8083063 Iustin Pop
    "highest_used_port",
1438 b2fddf63 Iustin Pop
    "tcpudp_port_pool",
1439 a8083063 Iustin Pop
    "mac_prefix",
1440 a8083063 Iustin Pop
    "volume_group_name",
1441 999b183c Iustin Pop
    "reserved_lvs",
1442 9e33896b Luca Bigliardi
    "drbd_usermode_helper",
1443 a8083063 Iustin Pop
    "default_bridge",
1444 02691904 Alexander Schreiber
    "default_hypervisor",
1445 f6bd6e98 Michael Hanselmann
    "master_node",
1446 f6bd6e98 Michael Hanselmann
    "master_ip",
1447 f6bd6e98 Michael Hanselmann
    "master_netdev",
1448 5a8648eb Andrea Spadaccini
    "master_netmask",
1449 33be7576 Andrea Spadaccini
    "use_external_mip_script",
1450 f6bd6e98 Michael Hanselmann
    "cluster_name",
1451 f6bd6e98 Michael Hanselmann
    "file_storage_dir",
1452 4b97f902 Apollon Oikonomopoulos
    "shared_file_storage_dir",
1453 e69d05fd Iustin Pop
    "enabled_hypervisors",
1454 5bf7b5cf Iustin Pop
    "hvparams",
1455 918eb80b Agata Murawska
    "ipolicy",
1456 17463d22 René Nussbaumer
    "os_hvp",
1457 5bf7b5cf Iustin Pop
    "beparams",
1458 1bdcbbab Iustin Pop
    "osparams",
1459 c8fcde47 Guido Trotter
    "nicparams",
1460 095e71aa René Nussbaumer
    "ndparams",
1461 bc5d0215 Andrea Spadaccini
    "diskparams",
1462 4b7735f9 Iustin Pop
    "candidate_pool_size",
1463 b86a6bcd Guido Trotter
    "modify_etc_hosts",
1464 b989b9d9 Ken Wehr
    "modify_ssh_setup",
1465 3953242f Iustin Pop
    "maintain_node_health",
1466 4437d889 Balazs Lecz
    "uid_pool",
1467 bf4af505 Apollon Oikonomopoulos
    "default_iallocator",
1468 87b2cd45 Iustin Pop
    "hidden_os",
1469 87b2cd45 Iustin Pop
    "blacklisted_os",
1470 2f20d07b Manuel Franceschini
    "primary_ip_family",
1471 3d914585 René Nussbaumer
    "prealloc_wipe_disks",
1472 2da9f556 René Nussbaumer
    "hv_state_static",
1473 2da9f556 René Nussbaumer
    "disk_state_static",
1474 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
1475 a8083063 Iustin Pop
1476 b86a6bcd Guido Trotter
  def UpgradeConfig(self):
1477 b86a6bcd Guido Trotter
    """Fill defaults for missing configuration values.
1478 b86a6bcd Guido Trotter

1479 b86a6bcd Guido Trotter
    """
1480 b459a848 Andrea Spadaccini
    # pylint: disable=E0203
1481 fe267188 Iustin Pop
    # because these are "defined" via slots, not manually
1482 c1b42c18 Guido Trotter
    if self.hvparams is None:
1483 c1b42c18 Guido Trotter
      self.hvparams = constants.HVC_DEFAULTS
1484 c1b42c18 Guido Trotter
    else:
1485 c1b42c18 Guido Trotter
      for hypervisor in self.hvparams:
1486 abe609b2 Guido Trotter
        self.hvparams[hypervisor] = FillDict(
1487 c1b42c18 Guido Trotter
            constants.HVC_DEFAULTS[hypervisor], self.hvparams[hypervisor])
1488 c1b42c18 Guido Trotter
1489 17463d22 René Nussbaumer
    if self.os_hvp is None:
1490 17463d22 René Nussbaumer
      self.os_hvp = {}
1491 17463d22 René Nussbaumer
1492 1bdcbbab Iustin Pop
    # osparams added before 2.2
1493 1bdcbbab Iustin Pop
    if self.osparams is None:
1494 1bdcbbab Iustin Pop
      self.osparams = {}
1495 1bdcbbab Iustin Pop
1496 2a27dac3 Iustin Pop
    self.ndparams = UpgradeNDParams(self.ndparams)
1497 095e71aa René Nussbaumer
1498 6e34b628 Guido Trotter
    self.beparams = UpgradeGroupedParams(self.beparams,
1499 6e34b628 Guido Trotter
                                         constants.BEC_DEFAULTS)
1500 8c72ab2b Guido Trotter
    for beparams_group in self.beparams:
1501 8c72ab2b Guido Trotter
      UpgradeBeParams(self.beparams[beparams_group])
1502 8c72ab2b Guido Trotter
1503 c8fcde47 Guido Trotter
    migrate_default_bridge = not self.nicparams
1504 c8fcde47 Guido Trotter
    self.nicparams = UpgradeGroupedParams(self.nicparams,
1505 c8fcde47 Guido Trotter
                                          constants.NICC_DEFAULTS)
1506 c8fcde47 Guido Trotter
    if migrate_default_bridge:
1507 c8fcde47 Guido Trotter
      self.nicparams[constants.PP_DEFAULT][constants.NIC_LINK] = \
1508 c8fcde47 Guido Trotter
        self.default_bridge
1509 c1b42c18 Guido Trotter
1510 b86a6bcd Guido Trotter
    if self.modify_etc_hosts is None:
1511 b86a6bcd Guido Trotter
      self.modify_etc_hosts = True
1512 b86a6bcd Guido Trotter
1513 b989b9d9 Ken Wehr
    if self.modify_ssh_setup is None:
1514 b989b9d9 Ken Wehr
      self.modify_ssh_setup = True
1515 b989b9d9 Ken Wehr
1516 73f1d185 Stephen Shirley
    # default_bridge is no longer used in 2.1. The slot is left there to
1517 90d118fd Guido Trotter
    # support auto-upgrading. It can be removed once we decide to deprecate
1518 90d118fd Guido Trotter
    # upgrading straight from 2.0.
1519 9b31ca85 Guido Trotter
    if self.default_bridge is not None:
1520 9b31ca85 Guido Trotter
      self.default_bridge = None
1521 9b31ca85 Guido Trotter
1522 90d118fd Guido Trotter
    # default_hypervisor is just the first enabled one in 2.1. This slot and
1523 90d118fd Guido Trotter
    # code can be removed once upgrading straight from 2.0 is deprecated.
1524 066f465d Guido Trotter
    if self.default_hypervisor is not None:
1525 016d04b3 Michael Hanselmann
      self.enabled_hypervisors = ([self.default_hypervisor] +
1526 5ae4945a Iustin Pop
                                  [hvname for hvname in self.enabled_hypervisors
1527 5ae4945a Iustin Pop
                                   if hvname != self.default_hypervisor])
1528 066f465d Guido Trotter
      self.default_hypervisor = None
1529 066f465d Guido Trotter
1530 3953242f Iustin Pop
    # maintain_node_health added after 2.1.1
1531 3953242f Iustin Pop
    if self.maintain_node_health is None:
1532 3953242f Iustin Pop
      self.maintain_node_health = False
1533 3953242f Iustin Pop
1534 4437d889 Balazs Lecz
    if self.uid_pool is None:
1535 4437d889 Balazs Lecz
      self.uid_pool = []
1536 4437d889 Balazs Lecz
1537 bf4af505 Apollon Oikonomopoulos
    if self.default_iallocator is None:
1538 bf4af505 Apollon Oikonomopoulos
      self.default_iallocator = ""
1539 bf4af505 Apollon Oikonomopoulos
1540 999b183c Iustin Pop
    # reserved_lvs added before 2.2
1541 999b183c Iustin Pop
    if self.reserved_lvs is None:
1542 999b183c Iustin Pop
      self.reserved_lvs = []
1543 999b183c Iustin Pop
1544 546b1111 Iustin Pop
    # hidden and blacklisted operating systems added before 2.2.1
1545 87b2cd45 Iustin Pop
    if self.hidden_os is None:
1546 87b2cd45 Iustin Pop
      self.hidden_os = []
1547 546b1111 Iustin Pop
1548 87b2cd45 Iustin Pop
    if self.blacklisted_os is None:
1549 87b2cd45 Iustin Pop
      self.blacklisted_os = []
1550 546b1111 Iustin Pop
1551 f4c9af7a Guido Trotter
    # primary_ip_family added before 2.3
1552 f4c9af7a Guido Trotter
    if self.primary_ip_family is None:
1553 f4c9af7a Guido Trotter
      self.primary_ip_family = AF_INET
1554 f4c9af7a Guido Trotter
1555 0007f3ab Andrea Spadaccini
    if self.master_netmask is None:
1556 0007f3ab Andrea Spadaccini
      ipcls = netutils.IPAddress.GetClassFromIpFamily(self.primary_ip_family)
1557 0007f3ab Andrea Spadaccini
      self.master_netmask = ipcls.iplen
1558 0007f3ab Andrea Spadaccini
1559 3d914585 René Nussbaumer
    if self.prealloc_wipe_disks is None:
1560 3d914585 René Nussbaumer
      self.prealloc_wipe_disks = False
1561 3d914585 René Nussbaumer
1562 e8f472d1 Iustin Pop
    # shared_file_storage_dir added before 2.5
1563 e8f472d1 Iustin Pop
    if self.shared_file_storage_dir is None:
1564 e8f472d1 Iustin Pop
      self.shared_file_storage_dir = ""
1565 e8f472d1 Iustin Pop
1566 33be7576 Andrea Spadaccini
    if self.use_external_mip_script is None:
1567 33be7576 Andrea Spadaccini
      self.use_external_mip_script = False
1568 33be7576 Andrea Spadaccini
1569 99ccf8b9 René Nussbaumer
    if self.diskparams:
1570 99ccf8b9 René Nussbaumer
      self.diskparams = UpgradeDiskParams(self.diskparams)
1571 99ccf8b9 René Nussbaumer
    else:
1572 99ccf8b9 René Nussbaumer
      self.diskparams = constants.DISK_DT_DEFAULTS.copy()
1573 bc5d0215 Andrea Spadaccini
1574 918eb80b Agata Murawska
    # instance policy added before 2.6
1575 918eb80b Agata Murawska
    if self.ipolicy is None:
1576 2cc673a3 Iustin Pop
      self.ipolicy = FillIPolicy(constants.IPOLICY_DEFAULTS, {})
1577 38a6e2e1 Iustin Pop
    else:
1578 38a6e2e1 Iustin Pop
      # we can either make sure to upgrade the ipolicy always, or only
1579 38a6e2e1 Iustin Pop
      # do it in some corner cases (e.g. missing keys); note that this
1580 38a6e2e1 Iustin Pop
      # will break any removal of keys from the ipolicy dict
1581 38a6e2e1 Iustin Pop
      self.ipolicy = FillIPolicy(constants.IPOLICY_DEFAULTS, self.ipolicy)
1582 918eb80b Agata Murawska
1583 0fbedb7a Michael Hanselmann
  @property
1584 0fbedb7a Michael Hanselmann
  def primary_hypervisor(self):
1585 0fbedb7a Michael Hanselmann
    """The first hypervisor is the primary.
1586 0fbedb7a Michael Hanselmann

1587 0fbedb7a Michael Hanselmann
    Useful, for example, for L{Node}'s hv/disk state.
1588 0fbedb7a Michael Hanselmann

1589 0fbedb7a Michael Hanselmann
    """
1590 0fbedb7a Michael Hanselmann
    return self.enabled_hypervisors[0]
1591 0fbedb7a Michael Hanselmann
1592 319856a9 Michael Hanselmann
  def ToDict(self):
1593 319856a9 Michael Hanselmann
    """Custom function for cluster.
1594 319856a9 Michael Hanselmann

1595 319856a9 Michael Hanselmann
    """
1596 b60ae2ca Iustin Pop
    mydict = super(Cluster, self).ToDict()
1597 319856a9 Michael Hanselmann
    mydict["tcpudp_port_pool"] = list(self.tcpudp_port_pool)
1598 319856a9 Michael Hanselmann
    return mydict
1599 319856a9 Michael Hanselmann
1600 319856a9 Michael Hanselmann
  @classmethod
1601 319856a9 Michael Hanselmann
  def FromDict(cls, val):
1602 319856a9 Michael Hanselmann
    """Custom function for cluster.
1603 319856a9 Michael Hanselmann

1604 319856a9 Michael Hanselmann
    """
1605 b60ae2ca Iustin Pop
    obj = super(Cluster, cls).FromDict(val)
1606 319856a9 Michael Hanselmann
    if not isinstance(obj.tcpudp_port_pool, set):
1607 319856a9 Michael Hanselmann
      obj.tcpudp_port_pool = set(obj.tcpudp_port_pool)
1608 319856a9 Michael Hanselmann
    return obj
1609 319856a9 Michael Hanselmann
1610 8a147bba René Nussbaumer
  def SimpleFillDP(self, diskparams):
1611 8a147bba René Nussbaumer
    """Fill a given diskparams dict with cluster defaults.
1612 8a147bba René Nussbaumer

1613 8a147bba René Nussbaumer
    @param diskparams: The diskparams
1614 8a147bba René Nussbaumer
    @return: The defaults dict
1615 8a147bba René Nussbaumer

1616 8a147bba René Nussbaumer
    """
1617 8a147bba René Nussbaumer
    return FillDiskParams(self.diskparams, diskparams)
1618 8a147bba René Nussbaumer
1619 d63479b5 Iustin Pop
  def GetHVDefaults(self, hypervisor, os_name=None, skip_keys=None):
1620 d63479b5 Iustin Pop
    """Get the default hypervisor parameters for the cluster.
1621 d63479b5 Iustin Pop

1622 d63479b5 Iustin Pop
    @param hypervisor: the hypervisor name
1623 d63479b5 Iustin Pop
    @param os_name: if specified, we'll also update the defaults for this OS
1624 d63479b5 Iustin Pop
    @param skip_keys: if passed, list of keys not to use
1625 d63479b5 Iustin Pop
    @return: the defaults dict
1626 d63479b5 Iustin Pop

1627 d63479b5 Iustin Pop
    """
1628 d63479b5 Iustin Pop
    if skip_keys is None:
1629 d63479b5 Iustin Pop
      skip_keys = []
1630 d63479b5 Iustin Pop
1631 d63479b5 Iustin Pop
    fill_stack = [self.hvparams.get(hypervisor, {})]
1632 d63479b5 Iustin Pop
    if os_name is not None:
1633 d63479b5 Iustin Pop
      os_hvp = self.os_hvp.get(os_name, {}).get(hypervisor, {})
1634 d63479b5 Iustin Pop
      fill_stack.append(os_hvp)
1635 d63479b5 Iustin Pop
1636 d63479b5 Iustin Pop
    ret_dict = {}
1637 d63479b5 Iustin Pop
    for o_dict in fill_stack:
1638 d63479b5 Iustin Pop
      ret_dict = FillDict(ret_dict, o_dict, skip_keys=skip_keys)
1639 d63479b5 Iustin Pop
1640 d63479b5 Iustin Pop
    return ret_dict
1641 d63479b5 Iustin Pop
1642 73e0328b Iustin Pop
  def SimpleFillHV(self, hv_name, os_name, hvparams, skip_globals=False):
1643 73e0328b Iustin Pop
    """Fill a given hvparams dict with cluster defaults.
1644 73e0328b Iustin Pop

1645 73e0328b Iustin Pop
    @type hv_name: string
1646 73e0328b Iustin Pop
    @param hv_name: the hypervisor to use
1647 73e0328b Iustin Pop
    @type os_name: string
1648 73e0328b Iustin Pop
    @param os_name: the OS to use for overriding the hypervisor defaults
1649 73e0328b Iustin Pop
    @type skip_globals: boolean
1650 73e0328b Iustin Pop
    @param skip_globals: if True, the global hypervisor parameters will
1651 73e0328b Iustin Pop
        not be filled
1652 73e0328b Iustin Pop
    @rtype: dict
1653 73e0328b Iustin Pop
    @return: a copy of the given hvparams with missing keys filled from
1654 73e0328b Iustin Pop
        the cluster defaults
1655 73e0328b Iustin Pop

1656 73e0328b Iustin Pop
    """
1657 73e0328b Iustin Pop
    if skip_globals:
1658 73e0328b Iustin Pop
      skip_keys = constants.HVC_GLOBALS
1659 73e0328b Iustin Pop
    else:
1660 73e0328b Iustin Pop
      skip_keys = []
1661 73e0328b Iustin Pop
1662 73e0328b Iustin Pop
    def_dict = self.GetHVDefaults(hv_name, os_name, skip_keys=skip_keys)
1663 73e0328b Iustin Pop
    return FillDict(def_dict, hvparams, skip_keys=skip_keys)
1664 d63479b5 Iustin Pop
1665 7736a5f2 Iustin Pop
  def FillHV(self, instance, skip_globals=False):
1666 73e0328b Iustin Pop
    """Fill an instance's hvparams dict with cluster defaults.
1667 5bf7b5cf Iustin Pop

1668 a2a24f4c Guido Trotter
    @type instance: L{objects.Instance}
1669 5bf7b5cf Iustin Pop
    @param instance: the instance parameter to fill
1670 7736a5f2 Iustin Pop
    @type skip_globals: boolean
1671 7736a5f2 Iustin Pop
    @param skip_globals: if True, the global hypervisor parameters will
1672 7736a5f2 Iustin Pop
        not be filled
1673 5bf7b5cf Iustin Pop
    @rtype: dict
1674 5bf7b5cf Iustin Pop
    @return: a copy of the instance's hvparams with missing keys filled from
1675 5bf7b5cf Iustin Pop
        the cluster defaults
1676 5bf7b5cf Iustin Pop

1677 5bf7b5cf Iustin Pop
    """
1678 73e0328b Iustin Pop
    return self.SimpleFillHV(instance.hypervisor, instance.os,
1679 73e0328b Iustin Pop
                             instance.hvparams, skip_globals)
1680 17463d22 René Nussbaumer
1681 73e0328b Iustin Pop
  def SimpleFillBE(self, beparams):
1682 73e0328b Iustin Pop
    """Fill a given beparams dict with cluster defaults.
1683 73e0328b Iustin Pop

1684 06596a60 Guido Trotter
    @type beparams: dict
1685 06596a60 Guido Trotter
    @param beparams: the dict to fill
1686 73e0328b Iustin Pop
    @rtype: dict
1687 73e0328b Iustin Pop
    @return: a copy of the passed in beparams with missing keys filled
1688 73e0328b Iustin Pop
        from the cluster defaults
1689 73e0328b Iustin Pop

1690 73e0328b Iustin Pop
    """
1691 73e0328b Iustin Pop
    return FillDict(self.beparams.get(constants.PP_DEFAULT, {}), beparams)
1692 5bf7b5cf Iustin Pop
1693 5bf7b5cf Iustin Pop
  def FillBE(self, instance):
1694 73e0328b Iustin Pop
    """Fill an instance's beparams dict with cluster defaults.
1695 5bf7b5cf Iustin Pop

1696 a2a24f4c Guido Trotter
    @type instance: L{objects.Instance}
1697 5bf7b5cf Iustin Pop
    @param instance: the instance parameter to fill
1698 5bf7b5cf Iustin Pop
    @rtype: dict
1699 5bf7b5cf Iustin Pop
    @return: a copy of the instance's beparams with missing keys filled from
1700 5bf7b5cf Iustin Pop
        the cluster defaults
1701 5bf7b5cf Iustin Pop

1702 5bf7b5cf Iustin Pop
    """
1703 73e0328b Iustin Pop
    return self.SimpleFillBE(instance.beparams)
1704 73e0328b Iustin Pop
1705 73e0328b Iustin Pop
  def SimpleFillNIC(self, nicparams):
1706 73e0328b Iustin Pop
    """Fill a given nicparams dict with cluster defaults.
1707 73e0328b Iustin Pop

1708 06596a60 Guido Trotter
    @type nicparams: dict
1709 06596a60 Guido Trotter
    @param nicparams: the dict to fill
1710 73e0328b Iustin Pop
    @rtype: dict
1711 73e0328b Iustin Pop
    @return: a copy of the passed in nicparams with missing keys filled
1712 73e0328b Iustin Pop
        from the cluster defaults
1713 73e0328b Iustin Pop

1714 73e0328b Iustin Pop
    """
1715 73e0328b Iustin Pop
    return FillDict(self.nicparams.get(constants.PP_DEFAULT, {}), nicparams)
1716 5bf7b5cf Iustin Pop
1717 1bdcbbab Iustin Pop
  def SimpleFillOS(self, os_name, os_params):
1718 1bdcbbab Iustin Pop
    """Fill an instance's osparams dict with cluster defaults.
1719 1bdcbbab Iustin Pop

1720 1bdcbbab Iustin Pop
    @type os_name: string
1721 1bdcbbab Iustin Pop
    @param os_name: the OS name to use
1722 1bdcbbab Iustin Pop
    @type os_params: dict
1723 1bdcbbab Iustin Pop
    @param os_params: the dict to fill with default values
1724 1bdcbbab Iustin Pop
    @rtype: dict
1725 1bdcbbab Iustin Pop
    @return: a copy of the instance's osparams with missing keys filled from
1726 1bdcbbab Iustin Pop
        the cluster defaults
1727 1bdcbbab Iustin Pop

1728 1bdcbbab Iustin Pop
    """
1729 1bdcbbab Iustin Pop
    name_only = os_name.split("+", 1)[0]
1730 1bdcbbab Iustin Pop
    # base OS
1731 1bdcbbab Iustin Pop
    result = self.osparams.get(name_only, {})
1732 1bdcbbab Iustin Pop
    # OS with variant
1733 1bdcbbab Iustin Pop
    result = FillDict(result, self.osparams.get(os_name, {}))
1734 1bdcbbab Iustin Pop
    # specified params
1735 1bdcbbab Iustin Pop
    return FillDict(result, os_params)
1736 1bdcbbab Iustin Pop
1737 2da9f556 René Nussbaumer
  @staticmethod
1738 2da9f556 René Nussbaumer
  def SimpleFillHvState(hv_state):
1739 2da9f556 René Nussbaumer
    """Fill an hv_state sub dict with cluster defaults.
1740 2da9f556 René Nussbaumer

1741 2da9f556 René Nussbaumer
    """
1742 2da9f556 René Nussbaumer
    return FillDict(constants.HVST_DEFAULTS, hv_state)
1743 2da9f556 René Nussbaumer
1744 2da9f556 René Nussbaumer
  @staticmethod
1745 2da9f556 René Nussbaumer
  def SimpleFillDiskState(disk_state):
1746 2da9f556 René Nussbaumer
    """Fill an disk_state sub dict with cluster defaults.
1747 2da9f556 René Nussbaumer

1748 2da9f556 René Nussbaumer
    """
1749 2da9f556 René Nussbaumer
    return FillDict(constants.DS_DEFAULTS, disk_state)
1750 2da9f556 René Nussbaumer
1751 095e71aa René Nussbaumer
  def FillND(self, node, nodegroup):
1752 ce523de1 Michael Hanselmann
    """Return filled out ndparams for L{objects.NodeGroup} and L{objects.Node}
1753 095e71aa René Nussbaumer

1754 095e71aa René Nussbaumer
    @type node: L{objects.Node}
1755 095e71aa René Nussbaumer
    @param node: A Node object to fill
1756 095e71aa René Nussbaumer
    @type nodegroup: L{objects.NodeGroup}
1757 095e71aa René Nussbaumer
    @param nodegroup: A Node object to fill
1758 095e71aa René Nussbaumer
    @return a copy of the node's ndparams with defaults filled
1759 095e71aa René Nussbaumer

1760 095e71aa René Nussbaumer
    """
1761 095e71aa René Nussbaumer
    return self.SimpleFillND(nodegroup.FillND(node))
1762 095e71aa René Nussbaumer
1763 095e71aa René Nussbaumer
  def SimpleFillND(self, ndparams):
1764 095e71aa René Nussbaumer
    """Fill a given ndparams dict with defaults.
1765 095e71aa René Nussbaumer

1766 095e71aa René Nussbaumer
    @type ndparams: dict
1767 095e71aa René Nussbaumer
    @param ndparams: the dict to fill
1768 095e71aa René Nussbaumer
    @rtype: dict
1769 095e71aa René Nussbaumer
    @return: a copy of the passed in ndparams with missing keys filled
1770 095e71aa René Nussbaumer
        from the cluster defaults
1771 095e71aa René Nussbaumer

1772 095e71aa René Nussbaumer
    """
1773 095e71aa René Nussbaumer
    return FillDict(self.ndparams, ndparams)
1774 095e71aa René Nussbaumer
1775 918eb80b Agata Murawska
  def SimpleFillIPolicy(self, ipolicy):
1776 918eb80b Agata Murawska
    """ Fill instance policy dict with defaults.
1777 918eb80b Agata Murawska

1778 918eb80b Agata Murawska
    @type ipolicy: dict
1779 918eb80b Agata Murawska
    @param ipolicy: the dict to fill
1780 918eb80b Agata Murawska
    @rtype: dict
1781 918eb80b Agata Murawska
    @return: a copy of passed ipolicy with missing keys filled from
1782 918eb80b Agata Murawska
      the cluster defaults
1783 918eb80b Agata Murawska

1784 918eb80b Agata Murawska
    """
1785 2cc673a3 Iustin Pop
    return FillIPolicy(self.ipolicy, ipolicy)
1786 918eb80b Agata Murawska
1787 5c947f38 Iustin Pop
1788 96acbc09 Michael Hanselmann
class BlockDevStatus(ConfigObject):
1789 96acbc09 Michael Hanselmann
  """Config object representing the status of a block device."""
1790 96acbc09 Michael Hanselmann
  __slots__ = [
1791 96acbc09 Michael Hanselmann
    "dev_path",
1792 96acbc09 Michael Hanselmann
    "major",
1793 96acbc09 Michael Hanselmann
    "minor",
1794 96acbc09 Michael Hanselmann
    "sync_percent",
1795 96acbc09 Michael Hanselmann
    "estimated_time",
1796 96acbc09 Michael Hanselmann
    "is_degraded",
1797 f208978a Michael Hanselmann
    "ldisk_status",
1798 96acbc09 Michael Hanselmann
    ]
1799 96acbc09 Michael Hanselmann
1800 96acbc09 Michael Hanselmann
1801 2d76b580 Michael Hanselmann
class ImportExportStatus(ConfigObject):
1802 2d76b580 Michael Hanselmann
  """Config object representing the status of an import or export."""
1803 2d76b580 Michael Hanselmann
  __slots__ = [
1804 2d76b580 Michael Hanselmann
    "recent_output",
1805 2d76b580 Michael Hanselmann
    "listen_port",
1806 2d76b580 Michael Hanselmann
    "connected",
1807 c08d76f5 Michael Hanselmann
    "progress_mbytes",
1808 c08d76f5 Michael Hanselmann
    "progress_throughput",
1809 c08d76f5 Michael Hanselmann
    "progress_eta",
1810 c08d76f5 Michael Hanselmann
    "progress_percent",
1811 2d76b580 Michael Hanselmann
    "exit_status",
1812 2d76b580 Michael Hanselmann
    "error_message",
1813 2d76b580 Michael Hanselmann
    ] + _TIMESTAMPS
1814 2d76b580 Michael Hanselmann
1815 2d76b580 Michael Hanselmann
1816 eb630f50 Michael Hanselmann
class ImportExportOptions(ConfigObject):
1817 eb630f50 Michael Hanselmann
  """Options for import/export daemon
1818 eb630f50 Michael Hanselmann

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

1826 eb630f50 Michael Hanselmann
  """
1827 eb630f50 Michael Hanselmann
  __slots__ = [
1828 eb630f50 Michael Hanselmann
    "key_name",
1829 eb630f50 Michael Hanselmann
    "ca_pem",
1830 a5310c2a Michael Hanselmann
    "compress",
1831 af1d39b1 Michael Hanselmann
    "magic",
1832 855d2fc7 Michael Hanselmann
    "ipv6",
1833 4478301b Michael Hanselmann
    "connect_timeout",
1834 eb630f50 Michael Hanselmann
    ]
1835 eb630f50 Michael Hanselmann
1836 eb630f50 Michael Hanselmann
1837 18d750b9 Guido Trotter
class ConfdRequest(ConfigObject):
1838 18d750b9 Guido Trotter
  """Object holding a confd request.
1839 18d750b9 Guido Trotter

1840 18d750b9 Guido Trotter
  @ivar protocol: confd protocol version
1841 18d750b9 Guido Trotter
  @ivar type: confd query type
1842 18d750b9 Guido Trotter
  @ivar query: query request
1843 18d750b9 Guido Trotter
  @ivar rsalt: requested reply salt
1844 18d750b9 Guido Trotter

1845 18d750b9 Guido Trotter
  """
1846 18d750b9 Guido Trotter
  __slots__ = [
1847 18d750b9 Guido Trotter
    "protocol",
1848 18d750b9 Guido Trotter
    "type",
1849 18d750b9 Guido Trotter
    "query",
1850 18d750b9 Guido Trotter
    "rsalt",
1851 18d750b9 Guido Trotter
    ]
1852 18d750b9 Guido Trotter
1853 18d750b9 Guido Trotter
1854 18d750b9 Guido Trotter
class ConfdReply(ConfigObject):
1855 18d750b9 Guido Trotter
  """Object holding a confd reply.
1856 18d750b9 Guido Trotter

1857 18d750b9 Guido Trotter
  @ivar protocol: confd protocol version
1858 18d750b9 Guido Trotter
  @ivar status: reply status code (ok, error)
1859 18d750b9 Guido Trotter
  @ivar answer: confd query reply
1860 18d750b9 Guido Trotter
  @ivar serial: configuration serial number
1861 18d750b9 Guido Trotter

1862 18d750b9 Guido Trotter
  """
1863 18d750b9 Guido Trotter
  __slots__ = [
1864 18d750b9 Guido Trotter
    "protocol",
1865 18d750b9 Guido Trotter
    "status",
1866 18d750b9 Guido Trotter
    "answer",
1867 18d750b9 Guido Trotter
    "serial",
1868 18d750b9 Guido Trotter
    ]
1869 18d750b9 Guido Trotter
1870 18d750b9 Guido Trotter
1871 707f23b5 Michael Hanselmann
class QueryFieldDefinition(ConfigObject):
1872 707f23b5 Michael Hanselmann
  """Object holding a query field definition.
1873 707f23b5 Michael Hanselmann

1874 24d6d3e2 Michael Hanselmann
  @ivar name: Field name
1875 707f23b5 Michael Hanselmann
  @ivar title: Human-readable title
1876 707f23b5 Michael Hanselmann
  @ivar kind: Field type
1877 1ae17369 Michael Hanselmann
  @ivar doc: Human-readable description
1878 707f23b5 Michael Hanselmann

1879 707f23b5 Michael Hanselmann
  """
1880 707f23b5 Michael Hanselmann
  __slots__ = [
1881 707f23b5 Michael Hanselmann
    "name",
1882 707f23b5 Michael Hanselmann
    "title",
1883 707f23b5 Michael Hanselmann
    "kind",
1884 1ae17369 Michael Hanselmann
    "doc",
1885 707f23b5 Michael Hanselmann
    ]
1886 707f23b5 Michael Hanselmann
1887 707f23b5 Michael Hanselmann
1888 0538c375 Michael Hanselmann
class _QueryResponseBase(ConfigObject):
1889 0538c375 Michael Hanselmann
  __slots__ = [
1890 0538c375 Michael Hanselmann
    "fields",
1891 0538c375 Michael Hanselmann
    ]
1892 0538c375 Michael Hanselmann
1893 0538c375 Michael Hanselmann
  def ToDict(self):
1894 0538c375 Michael Hanselmann
    """Custom function for serializing.
1895 0538c375 Michael Hanselmann

1896 0538c375 Michael Hanselmann
    """
1897 0538c375 Michael Hanselmann
    mydict = super(_QueryResponseBase, self).ToDict()
1898 0538c375 Michael Hanselmann
    mydict["fields"] = self._ContainerToDicts(mydict["fields"])
1899 0538c375 Michael Hanselmann
    return mydict
1900 0538c375 Michael Hanselmann
1901 0538c375 Michael Hanselmann
  @classmethod
1902 0538c375 Michael Hanselmann
  def FromDict(cls, val):
1903 0538c375 Michael Hanselmann
    """Custom function for de-serializing.
1904 0538c375 Michael Hanselmann

1905 0538c375 Michael Hanselmann
    """
1906 0538c375 Michael Hanselmann
    obj = super(_QueryResponseBase, cls).FromDict(val)
1907 0538c375 Michael Hanselmann
    obj.fields = cls._ContainerFromDicts(obj.fields, list, QueryFieldDefinition)
1908 0538c375 Michael Hanselmann
    return obj
1909 0538c375 Michael Hanselmann
1910 0538c375 Michael Hanselmann
1911 0538c375 Michael Hanselmann
class QueryResponse(_QueryResponseBase):
1912 24d6d3e2 Michael Hanselmann
  """Object holding the response to a query.
1913 24d6d3e2 Michael Hanselmann

1914 24d6d3e2 Michael Hanselmann
  @ivar fields: List of L{QueryFieldDefinition} objects
1915 24d6d3e2 Michael Hanselmann
  @ivar data: Requested data
1916 24d6d3e2 Michael Hanselmann

1917 24d6d3e2 Michael Hanselmann
  """
1918 24d6d3e2 Michael Hanselmann
  __slots__ = [
1919 24d6d3e2 Michael Hanselmann
    "data",
1920 24d6d3e2 Michael Hanselmann
    ]
1921 24d6d3e2 Michael Hanselmann
1922 24d6d3e2 Michael Hanselmann
1923 24d6d3e2 Michael Hanselmann
class QueryFieldsRequest(ConfigObject):
1924 24d6d3e2 Michael Hanselmann
  """Object holding a request for querying available fields.
1925 24d6d3e2 Michael Hanselmann

1926 24d6d3e2 Michael Hanselmann
  """
1927 24d6d3e2 Michael Hanselmann
  __slots__ = [
1928 24d6d3e2 Michael Hanselmann
    "what",
1929 24d6d3e2 Michael Hanselmann
    "fields",
1930 24d6d3e2 Michael Hanselmann
    ]
1931 24d6d3e2 Michael Hanselmann
1932 24d6d3e2 Michael Hanselmann
1933 0538c375 Michael Hanselmann
class QueryFieldsResponse(_QueryResponseBase):
1934 24d6d3e2 Michael Hanselmann
  """Object holding the response to a query for fields.
1935 24d6d3e2 Michael Hanselmann

1936 24d6d3e2 Michael Hanselmann
  @ivar fields: List of L{QueryFieldDefinition} objects
1937 24d6d3e2 Michael Hanselmann

1938 24d6d3e2 Michael Hanselmann
  """
1939 5ae4945a Iustin Pop
  __slots__ = []
1940 24d6d3e2 Michael Hanselmann
1941 24d6d3e2 Michael Hanselmann
1942 6a1434d7 Andrea Spadaccini
class MigrationStatus(ConfigObject):
1943 6a1434d7 Andrea Spadaccini
  """Object holding the status of a migration.
1944 6a1434d7 Andrea Spadaccini

1945 6a1434d7 Andrea Spadaccini
  """
1946 6a1434d7 Andrea Spadaccini
  __slots__ = [
1947 6a1434d7 Andrea Spadaccini
    "status",
1948 6a1434d7 Andrea Spadaccini
    "transferred_ram",
1949 6a1434d7 Andrea Spadaccini
    "total_ram",
1950 6a1434d7 Andrea Spadaccini
    ]
1951 6a1434d7 Andrea Spadaccini
1952 6a1434d7 Andrea Spadaccini
1953 25ce3ec4 Michael Hanselmann
class InstanceConsole(ConfigObject):
1954 25ce3ec4 Michael Hanselmann
  """Object describing how to access the console of an instance.
1955 25ce3ec4 Michael Hanselmann

1956 25ce3ec4 Michael Hanselmann
  """
1957 25ce3ec4 Michael Hanselmann
  __slots__ = [
1958 25ce3ec4 Michael Hanselmann
    "instance",
1959 25ce3ec4 Michael Hanselmann
    "kind",
1960 25ce3ec4 Michael Hanselmann
    "message",
1961 25ce3ec4 Michael Hanselmann
    "host",
1962 25ce3ec4 Michael Hanselmann
    "port",
1963 25ce3ec4 Michael Hanselmann
    "user",
1964 25ce3ec4 Michael Hanselmann
    "command",
1965 25ce3ec4 Michael Hanselmann
    "display",
1966 25ce3ec4 Michael Hanselmann
    ]
1967 25ce3ec4 Michael Hanselmann
1968 25ce3ec4 Michael Hanselmann
  def Validate(self):
1969 25ce3ec4 Michael Hanselmann
    """Validates contents of this object.
1970 25ce3ec4 Michael Hanselmann

1971 25ce3ec4 Michael Hanselmann
    """
1972 25ce3ec4 Michael Hanselmann
    assert self.kind in constants.CONS_ALL, "Unknown console type"
1973 25ce3ec4 Michael Hanselmann
    assert self.instance, "Missing instance name"
1974 4d2cdb5a Andrea Spadaccini
    assert self.message or self.kind in [constants.CONS_SSH,
1975 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1976 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_VNC]
1977 25ce3ec4 Michael Hanselmann
    assert self.host or self.kind == constants.CONS_MESSAGE
1978 25ce3ec4 Michael Hanselmann
    assert self.port or self.kind in [constants.CONS_MESSAGE,
1979 25ce3ec4 Michael Hanselmann
                                      constants.CONS_SSH]
1980 25ce3ec4 Michael Hanselmann
    assert self.user or self.kind in [constants.CONS_MESSAGE,
1981 4d2cdb5a Andrea Spadaccini
                                      constants.CONS_SPICE,
1982 25ce3ec4 Michael Hanselmann
                                      constants.CONS_VNC]
1983 25ce3ec4 Michael Hanselmann
    assert self.command or self.kind in [constants.CONS_MESSAGE,
1984 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1985 25ce3ec4 Michael Hanselmann
                                         constants.CONS_VNC]
1986 25ce3ec4 Michael Hanselmann
    assert self.display or self.kind in [constants.CONS_MESSAGE,
1987 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1988 25ce3ec4 Michael Hanselmann
                                         constants.CONS_SSH]
1989 25ce3ec4 Michael Hanselmann
    return True
1990 25ce3ec4 Michael Hanselmann
1991 25ce3ec4 Michael Hanselmann
1992 a8083063 Iustin Pop
class SerializableConfigParser(ConfigParser.SafeConfigParser):
1993 a8083063 Iustin Pop
  """Simple wrapper over ConfigParse that allows serialization.
1994 a8083063 Iustin Pop

1995 a8083063 Iustin Pop
  This class is basically ConfigParser.SafeConfigParser with two
1996 a8083063 Iustin Pop
  additional methods that allow it to serialize/unserialize to/from a
1997 a8083063 Iustin Pop
  buffer.
1998 a8083063 Iustin Pop

1999 a8083063 Iustin Pop
  """
2000 a8083063 Iustin Pop
  def Dumps(self):
2001 a8083063 Iustin Pop
    """Dump this instance and return the string representation."""
2002 a8083063 Iustin Pop
    buf = StringIO()
2003 a8083063 Iustin Pop
    self.write(buf)
2004 a8083063 Iustin Pop
    return buf.getvalue()
2005 a8083063 Iustin Pop
2006 b39bf4bb Guido Trotter
  @classmethod
2007 b39bf4bb Guido Trotter
  def Loads(cls, data):
2008 a8083063 Iustin Pop
    """Load data from a string."""
2009 a8083063 Iustin Pop
    buf = StringIO(data)
2010 b39bf4bb Guido Trotter
    cfp = cls()
2011 a8083063 Iustin Pop
    cfp.readfp(buf)
2012 a8083063 Iustin Pop
    return cfp