Statistics
| Branch: | Tag: | Revision:

root / lib / objects.py @ 1c4910f7

History | View | Annotate | Download (71.9 kB)

1 2f31098c Iustin Pop
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 8a5d326f Jose A. Lopes
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 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 250a9404 Bernardo Dal Seno
import logging
42 e11a1b77 Adeodato Simo
import time
43 d5835922 Michael Hanselmann
from cStringIO import StringIO
44 a8083063 Iustin Pop
45 a8083063 Iustin Pop
from ganeti import errors
46 5c947f38 Iustin Pop
from ganeti import constants
47 0007f3ab Andrea Spadaccini
from ganeti import netutils
48 473d87a3 Iustin Pop
from ganeti import outils
49 32017174 Agata Murawska
from ganeti import utils
50 a5efec93 Santi Raffa
from ganeti import serializer
51 a8083063 Iustin Pop
52 f4c9af7a Guido Trotter
from socket import AF_INET
53 f4c9af7a Guido Trotter
54 a8083063 Iustin Pop
55 a8083063 Iustin Pop
__all__ = ["ConfigObject", "ConfigData", "NIC", "Disk", "Instance",
56 eaa4c57c Dimitris Aragiorgis
           "OS", "Node", "NodeGroup", "Cluster", "FillDict", "Network"]
57 a8083063 Iustin Pop
58 d693c864 Iustin Pop
_TIMESTAMPS = ["ctime", "mtime"]
59 e1dcc53a Iustin Pop
_UUID = ["uuid"]
60 96acbc09 Michael Hanselmann
61 8d8d650c Michael Hanselmann
62 e11ddf13 Iustin Pop
def FillDict(defaults_dict, custom_dict, skip_keys=None):
63 29921401 Iustin Pop
  """Basic function to apply settings on top a default dict.
64 abe609b2 Guido Trotter

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

74 29921401 Iustin Pop
  """
75 29921401 Iustin Pop
  ret_dict = copy.deepcopy(defaults_dict)
76 29921401 Iustin Pop
  ret_dict.update(custom_dict)
77 e11ddf13 Iustin Pop
  if skip_keys:
78 e11ddf13 Iustin Pop
    for k in skip_keys:
79 e4236bbd Santi Raffa
      if k in ret_dict:
80 e11ddf13 Iustin Pop
        del ret_dict[k]
81 29921401 Iustin Pop
  return ret_dict
82 a8083063 Iustin Pop
83 6e34b628 Guido Trotter
84 da5f09ef Bernardo Dal Seno
def FillIPolicy(default_ipolicy, custom_ipolicy):
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 0f511c8a Bernardo Dal Seno
  ret_dict = copy.deepcopy(custom_ipolicy)
90 0f511c8a Bernardo Dal Seno
  for key in default_ipolicy:
91 0f511c8a Bernardo Dal Seno
    if key not in ret_dict:
92 0f511c8a Bernardo Dal Seno
      ret_dict[key] = copy.deepcopy(default_ipolicy[key])
93 0f511c8a Bernardo Dal Seno
    elif key == constants.ISPECS_STD:
94 0f511c8a Bernardo Dal Seno
      ret_dict[key] = FillDict(default_ipolicy[key], ret_dict[key])
95 918eb80b Agata Murawska
  return ret_dict
96 918eb80b Agata Murawska
97 918eb80b Agata Murawska
98 57987785 Renรฉ Nussbaumer
def FillDiskParams(default_dparams, custom_dparams, skip_keys=None):
99 57987785 Renรฉ Nussbaumer
  """Fills the disk parameter defaults.
100 57987785 Renรฉ Nussbaumer

101 af9fb4cc Renรฉ Nussbaumer
  @see: L{FillDict} for parameters and return value
102 57987785 Renรฉ Nussbaumer

103 57987785 Renรฉ Nussbaumer
  """
104 57987785 Renรฉ Nussbaumer
  assert frozenset(default_dparams.keys()) == constants.DISK_TEMPLATES
105 57987785 Renรฉ Nussbaumer
106 57987785 Renรฉ Nussbaumer
  return dict((dt, FillDict(default_dparams[dt], custom_dparams.get(dt, {}),
107 57987785 Renรฉ Nussbaumer
                             skip_keys=skip_keys))
108 57987785 Renรฉ Nussbaumer
              for dt in constants.DISK_TEMPLATES)
109 57987785 Renรฉ Nussbaumer
110 57987785 Renรฉ Nussbaumer
111 6e34b628 Guido Trotter
def UpgradeGroupedParams(target, defaults):
112 6e34b628 Guido Trotter
  """Update all groups for the target parameter.
113 6e34b628 Guido Trotter

114 6e34b628 Guido Trotter
  @type target: dict of dicts
115 6e34b628 Guido Trotter
  @param target: {group: {parameter: value}}
116 6e34b628 Guido Trotter
  @type defaults: dict
117 6e34b628 Guido Trotter
  @param defaults: default parameter values
118 6e34b628 Guido Trotter

119 6e34b628 Guido Trotter
  """
120 6e34b628 Guido Trotter
  if target is None:
121 6e34b628 Guido Trotter
    target = {constants.PP_DEFAULT: defaults}
122 6e34b628 Guido Trotter
  else:
123 6e34b628 Guido Trotter
    for group in target:
124 6e34b628 Guido Trotter
      target[group] = FillDict(defaults, target[group])
125 6e34b628 Guido Trotter
  return target
126 6e34b628 Guido Trotter
127 6e34b628 Guido Trotter
128 8c72ab2b Guido Trotter
def UpgradeBeParams(target):
129 8c72ab2b Guido Trotter
  """Update the be parameters dict to the new format.
130 8c72ab2b Guido Trotter

131 8c72ab2b Guido Trotter
  @type target: dict
132 8c72ab2b Guido Trotter
  @param target: "be" parameters dict
133 8c72ab2b Guido Trotter

134 8c72ab2b Guido Trotter
  """
135 8c72ab2b Guido Trotter
  if constants.BE_MEMORY in target:
136 8c72ab2b Guido Trotter
    memory = target[constants.BE_MEMORY]
137 8c72ab2b Guido Trotter
    target[constants.BE_MAXMEM] = memory
138 8c72ab2b Guido Trotter
    target[constants.BE_MINMEM] = memory
139 b2e233a5 Guido Trotter
    del target[constants.BE_MEMORY]
140 8c72ab2b Guido Trotter
141 8c72ab2b Guido Trotter
142 bc5d0215 Andrea Spadaccini
def UpgradeDiskParams(diskparams):
143 bc5d0215 Andrea Spadaccini
  """Upgrade the disk parameters.
144 bc5d0215 Andrea Spadaccini

145 bc5d0215 Andrea Spadaccini
  @type diskparams: dict
146 bc5d0215 Andrea Spadaccini
  @param diskparams: disk parameters to upgrade
147 bc5d0215 Andrea Spadaccini
  @rtype: dict
148 765ada2b Iustin Pop
  @return: the upgraded disk parameters dict
149 bc5d0215 Andrea Spadaccini

150 bc5d0215 Andrea Spadaccini
  """
151 99ccf8b9 Renรฉ Nussbaumer
  if not diskparams:
152 99ccf8b9 Renรฉ Nussbaumer
    result = {}
153 bc5d0215 Andrea Spadaccini
  else:
154 57987785 Renรฉ Nussbaumer
    result = FillDiskParams(constants.DISK_DT_DEFAULTS, diskparams)
155 bc5d0215 Andrea Spadaccini
156 bc5d0215 Andrea Spadaccini
  return result
157 bc5d0215 Andrea Spadaccini
158 bc5d0215 Andrea Spadaccini
159 2a27dac3 Iustin Pop
def UpgradeNDParams(ndparams):
160 2a27dac3 Iustin Pop
  """Upgrade ndparams structure.
161 2a27dac3 Iustin Pop

162 2a27dac3 Iustin Pop
  @type ndparams: dict
163 2a27dac3 Iustin Pop
  @param ndparams: disk parameters to upgrade
164 2a27dac3 Iustin Pop
  @rtype: dict
165 2a27dac3 Iustin Pop
  @return: the upgraded node parameters dict
166 2a27dac3 Iustin Pop

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

181 918eb80b Agata Murawska
  """
182 0f511c8a Bernardo Dal Seno
  return {}
183 918eb80b Agata Murawska
184 918eb80b Agata Murawska
185 473d87a3 Iustin Pop
class ConfigObject(outils.ValidatedSlots):
186 a8083063 Iustin Pop
  """A generic config object.
187 a8083063 Iustin Pop

188 a8083063 Iustin Pop
  It has the following properties:
189 a8083063 Iustin Pop

190 a8083063 Iustin Pop
    - provides somewhat safe recursive unpickling and pickling for its classes
191 a8083063 Iustin Pop
    - unset attributes which are defined in slots are always returned
192 a8083063 Iustin Pop
      as None instead of raising an error
193 a8083063 Iustin Pop

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

197 a8083063 Iustin Pop
  """
198 a8083063 Iustin Pop
  __slots__ = []
199 a8083063 Iustin Pop
200 a8083063 Iustin Pop
  def __getattr__(self, name):
201 32683096 Renรฉ Nussbaumer
    if name not in self.GetAllSlots():
202 3ecf6786 Iustin Pop
      raise AttributeError("Invalid object attribute %s.%s" %
203 3ecf6786 Iustin Pop
                           (type(self).__name__, name))
204 a8083063 Iustin Pop
    return None
205 a8083063 Iustin Pop
206 a8083063 Iustin Pop
  def __setstate__(self, state):
207 32683096 Renรฉ Nussbaumer
    slots = self.GetAllSlots()
208 a8083063 Iustin Pop
    for name in state:
209 adf385c7 Iustin Pop
      if name in slots:
210 a8083063 Iustin Pop
        setattr(self, name, state[name])
211 a8083063 Iustin Pop
212 32683096 Renรฉ Nussbaumer
  def Validate(self):
213 32683096 Renรฉ Nussbaumer
    """Validates the slots.
214 adf385c7 Iustin Pop

215 b3724640 Jose A. Lopes
    This method returns L{None} if the validation succeeds, or raises
216 b3724640 Jose A. Lopes
    an exception otherwise.
217 b3724640 Jose A. Lopes

218 b3724640 Jose A. Lopes
    This method must be implemented by the child classes.
219 b3724640 Jose A. Lopes

220 b3724640 Jose A. Lopes
    @rtype: NoneType
221 b3724640 Jose A. Lopes
    @return: L{None}, if the validation succeeds
222 b3724640 Jose A. Lopes

223 b3724640 Jose A. Lopes
    @raise Exception: validation fails
224 b3724640 Jose A. Lopes

225 adf385c7 Iustin Pop
    """
226 415feb2e Renรฉ Nussbaumer
227 a5efec93 Santi Raffa
  def ToDict(self, _with_private=False):
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 a5efec93 Santi Raffa
    Private fields can be included or not with the _with_private switch.
237 a5efec93 Santi Raffa
    The actual implementation of this switch is left for those subclassses
238 a5efec93 Santi Raffa
    with private fields to implement.
239 a5efec93 Santi Raffa

240 a5efec93 Santi Raffa
    @type _with_private: bool
241 a5efec93 Santi Raffa
    @param _with_private: if True, the object will leak its private fields in
242 a5efec93 Santi Raffa
                          the dictionary representation. If False, the values
243 a5efec93 Santi Raffa
                          will be replaced with None.
244 a5efec93 Santi Raffa

245 ff9c047c Iustin Pop
    """
246 4c14965f Guido Trotter
    result = {}
247 32683096 Renรฉ Nussbaumer
    for name in self.GetAllSlots():
248 4c14965f Guido Trotter
      value = getattr(self, name, None)
249 4c14965f Guido Trotter
      if value is not None:
250 4c14965f Guido Trotter
        result[name] = value
251 4c14965f Guido Trotter
    return result
252 4c14965f Guido Trotter
253 4c14965f Guido Trotter
  __getstate__ = ToDict
254 ff9c047c Iustin Pop
255 ff9c047c Iustin Pop
  @classmethod
256 ff9c047c Iustin Pop
  def FromDict(cls, val):
257 ff9c047c Iustin Pop
    """Create an object from a dictionary.
258 ff9c047c Iustin Pop

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

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

267 ff9c047c Iustin Pop
    """
268 ff9c047c Iustin Pop
    if not isinstance(val, dict):
269 ff9c047c Iustin Pop
      raise errors.ConfigurationError("Invalid object passed to FromDict:"
270 ff9c047c Iustin Pop
                                      " expected dict, got %s" % type(val))
271 319856a9 Michael Hanselmann
    val_str = dict([(str(k), v) for k, v in val.iteritems()])
272 b459a848 Andrea Spadaccini
    obj = cls(**val_str) # pylint: disable=W0142
273 ff9c047c Iustin Pop
    return obj
274 ff9c047c Iustin Pop
275 e8d563f3 Iustin Pop
  def Copy(self):
276 e8d563f3 Iustin Pop
    """Makes a deep copy of the current object and its children.
277 e8d563f3 Iustin Pop

278 e8d563f3 Iustin Pop
    """
279 e8d563f3 Iustin Pop
    dict_form = self.ToDict()
280 e8d563f3 Iustin Pop
    clone_obj = self.__class__.FromDict(dict_form)
281 e8d563f3 Iustin Pop
    return clone_obj
282 e8d563f3 Iustin Pop
283 ff9c047c Iustin Pop
  def __repr__(self):
284 ff9c047c Iustin Pop
    """Implement __repr__ for ConfigObjects."""
285 ff9c047c Iustin Pop
    return repr(self.ToDict())
286 ff9c047c Iustin Pop
287 19830e88 Thomas Thrainer
  def __eq__(self, other):
288 19830e88 Thomas Thrainer
    """Implement __eq__ for ConfigObjects."""
289 19830e88 Thomas Thrainer
    return isinstance(other, self.__class__) and self.ToDict() == other.ToDict()
290 19830e88 Thomas Thrainer
291 560428be Guido Trotter
  def UpgradeConfig(self):
292 560428be Guido Trotter
    """Fill defaults for missing configuration values.
293 560428be Guido Trotter

294 90d726a8 Iustin Pop
    This method will be called at configuration load time, and its
295 90d726a8 Iustin Pop
    implementation will be object dependent.
296 560428be Guido Trotter

297 560428be Guido Trotter
    """
298 560428be Guido Trotter
    pass
299 560428be Guido Trotter
300 a8083063 Iustin Pop
301 ec29fe40 Iustin Pop
class TaggableObject(ConfigObject):
302 5c947f38 Iustin Pop
  """An generic class supporting tags.
303 5c947f38 Iustin Pop

304 5c947f38 Iustin Pop
  """
305 154b9580 Balazs Lecz
  __slots__ = ["tags"]
306 78f99abb Michele Tartara
  VALID_TAG_RE = re.compile(r"^[\w.+*/:@-]+$")
307 2057f6c7 Iustin Pop
308 b5e5632e Iustin Pop
  @classmethod
309 b5e5632e Iustin Pop
  def ValidateTag(cls, tag):
310 5c947f38 Iustin Pop
    """Check if a tag is valid.
311 5c947f38 Iustin Pop

312 5c947f38 Iustin Pop
    If the tag is invalid, an errors.TagError will be raised. The
313 5c947f38 Iustin Pop
    function has no return value.
314 5c947f38 Iustin Pop

315 5c947f38 Iustin Pop
    """
316 5c947f38 Iustin Pop
    if not isinstance(tag, basestring):
317 3ecf6786 Iustin Pop
      raise errors.TagError("Invalid tag type (not a string)")
318 5c947f38 Iustin Pop
    if len(tag) > constants.MAX_TAG_LEN:
319 319856a9 Michael Hanselmann
      raise errors.TagError("Tag too long (>%d characters)" %
320 319856a9 Michael Hanselmann
                            constants.MAX_TAG_LEN)
321 5c947f38 Iustin Pop
    if not tag:
322 3ecf6786 Iustin Pop
      raise errors.TagError("Tags cannot be empty")
323 b5e5632e Iustin Pop
    if not cls.VALID_TAG_RE.match(tag):
324 3ecf6786 Iustin Pop
      raise errors.TagError("Tag contains invalid characters")
325 5c947f38 Iustin Pop
326 5c947f38 Iustin Pop
  def GetTags(self):
327 5c947f38 Iustin Pop
    """Return the tags list.
328 5c947f38 Iustin Pop

329 5c947f38 Iustin Pop
    """
330 5c947f38 Iustin Pop
    tags = getattr(self, "tags", None)
331 5c947f38 Iustin Pop
    if tags is None:
332 5c947f38 Iustin Pop
      tags = self.tags = set()
333 5c947f38 Iustin Pop
    return tags
334 5c947f38 Iustin Pop
335 5c947f38 Iustin Pop
  def AddTag(self, tag):
336 5c947f38 Iustin Pop
    """Add a new tag.
337 5c947f38 Iustin Pop

338 5c947f38 Iustin Pop
    """
339 5c947f38 Iustin Pop
    self.ValidateTag(tag)
340 5c947f38 Iustin Pop
    tags = self.GetTags()
341 5c947f38 Iustin Pop
    if len(tags) >= constants.MAX_TAGS_PER_OBJ:
342 3ecf6786 Iustin Pop
      raise errors.TagError("Too many tags")
343 5c947f38 Iustin Pop
    self.GetTags().add(tag)
344 5c947f38 Iustin Pop
345 5c947f38 Iustin Pop
  def RemoveTag(self, tag):
346 5c947f38 Iustin Pop
    """Remove a tag.
347 5c947f38 Iustin Pop

348 5c947f38 Iustin Pop
    """
349 5c947f38 Iustin Pop
    self.ValidateTag(tag)
350 5c947f38 Iustin Pop
    tags = self.GetTags()
351 5c947f38 Iustin Pop
    try:
352 5c947f38 Iustin Pop
      tags.remove(tag)
353 5c947f38 Iustin Pop
    except KeyError:
354 3ecf6786 Iustin Pop
      raise errors.TagError("Tag not found")
355 5c947f38 Iustin Pop
356 a5efec93 Santi Raffa
  def ToDict(self, _with_private=False):
357 ff9c047c Iustin Pop
    """Taggable-object-specific conversion to standard python types.
358 ff9c047c Iustin Pop

359 ff9c047c Iustin Pop
    This replaces the tags set with a list.
360 ff9c047c Iustin Pop

361 ff9c047c Iustin Pop
    """
362 a5efec93 Santi Raffa
    bo = super(TaggableObject, self).ToDict(_with_private=_with_private)
363 ff9c047c Iustin Pop
364 ff9c047c Iustin Pop
    tags = bo.get("tags", None)
365 ff9c047c Iustin Pop
    if isinstance(tags, set):
366 ff9c047c Iustin Pop
      bo["tags"] = list(tags)
367 ff9c047c Iustin Pop
    return bo
368 ff9c047c Iustin Pop
369 ff9c047c Iustin Pop
  @classmethod
370 ff9c047c Iustin Pop
  def FromDict(cls, val):
371 ff9c047c Iustin Pop
    """Custom function for instances.
372 ff9c047c Iustin Pop

373 ff9c047c Iustin Pop
    """
374 ff9c047c Iustin Pop
    obj = super(TaggableObject, cls).FromDict(val)
375 ff9c047c Iustin Pop
    if hasattr(obj, "tags") and isinstance(obj.tags, list):
376 ff9c047c Iustin Pop
      obj.tags = set(obj.tags)
377 ff9c047c Iustin Pop
    return obj
378 ff9c047c Iustin Pop
379 5c947f38 Iustin Pop
380 061af273 Andrea Spadaccini
class MasterNetworkParameters(ConfigObject):
381 061af273 Andrea Spadaccini
  """Network configuration parameters for the master
382 061af273 Andrea Spadaccini

383 1c3231aa Thomas Thrainer
  @ivar uuid: master nodes UUID
384 061af273 Andrea Spadaccini
  @ivar ip: master IP
385 061af273 Andrea Spadaccini
  @ivar netmask: master netmask
386 061af273 Andrea Spadaccini
  @ivar netdev: master network device
387 061af273 Andrea Spadaccini
  @ivar ip_family: master IP family
388 061af273 Andrea Spadaccini

389 061af273 Andrea Spadaccini
  """
390 061af273 Andrea Spadaccini
  __slots__ = [
391 1c3231aa Thomas Thrainer
    "uuid",
392 061af273 Andrea Spadaccini
    "ip",
393 061af273 Andrea Spadaccini
    "netmask",
394 061af273 Andrea Spadaccini
    "netdev",
395 3c286190 Dimitris Aragiorgis
    "ip_family",
396 061af273 Andrea Spadaccini
    ]
397 061af273 Andrea Spadaccini
398 061af273 Andrea Spadaccini
399 a8083063 Iustin Pop
class ConfigData(ConfigObject):
400 a8083063 Iustin Pop
  """Top-level config object."""
401 3df43542 Guido Trotter
  __slots__ = [
402 3df43542 Guido Trotter
    "version",
403 3df43542 Guido Trotter
    "cluster",
404 3df43542 Guido Trotter
    "nodes",
405 3df43542 Guido Trotter
    "nodegroups",
406 3df43542 Guido Trotter
    "instances",
407 eaa4c57c Dimitris Aragiorgis
    "networks",
408 3df43542 Guido Trotter
    "serial_no",
409 3df43542 Guido Trotter
    ] + _TIMESTAMPS
410 a8083063 Iustin Pop
411 a5efec93 Santi Raffa
  def ToDict(self, _with_private=False):
412 ff9c047c Iustin Pop
    """Custom function for top-level config data.
413 ff9c047c Iustin Pop

414 ff9c047c Iustin Pop
    This just replaces the list of instances, nodes and the cluster
415 ff9c047c Iustin Pop
    with standard python types.
416 ff9c047c Iustin Pop

417 ff9c047c Iustin Pop
    """
418 a5efec93 Santi Raffa
    mydict = super(ConfigData, self).ToDict(_with_private=_with_private)
419 ff9c047c Iustin Pop
    mydict["cluster"] = mydict["cluster"].ToDict()
420 eaa4c57c Dimitris Aragiorgis
    for key in "nodes", "instances", "nodegroups", "networks":
421 fe502d25 Iustin Pop
      mydict[key] = outils.ContainerToDicts(mydict[key])
422 ff9c047c Iustin Pop
423 ff9c047c Iustin Pop
    return mydict
424 ff9c047c Iustin Pop
425 ff9c047c Iustin Pop
  @classmethod
426 ff9c047c Iustin Pop
  def FromDict(cls, val):
427 ff9c047c Iustin Pop
    """Custom function for top-level config data
428 ff9c047c Iustin Pop

429 ff9c047c Iustin Pop
    """
430 ff9c047c Iustin Pop
    obj = super(ConfigData, cls).FromDict(val)
431 ff9c047c Iustin Pop
    obj.cluster = Cluster.FromDict(obj.cluster)
432 fe502d25 Iustin Pop
    obj.nodes = outils.ContainerFromDicts(obj.nodes, dict, Node)
433 473ab806 Michael Hanselmann
    obj.instances = \
434 fe502d25 Iustin Pop
      outils.ContainerFromDicts(obj.instances, dict, Instance)
435 473ab806 Michael Hanselmann
    obj.nodegroups = \
436 fe502d25 Iustin Pop
      outils.ContainerFromDicts(obj.nodegroups, dict, NodeGroup)
437 fe502d25 Iustin Pop
    obj.networks = outils.ContainerFromDicts(obj.networks, dict, Network)
438 ff9c047c Iustin Pop
    return obj
439 ff9c047c Iustin Pop
440 51cb1581 Luca Bigliardi
  def HasAnyDiskOfType(self, dev_type):
441 51cb1581 Luca Bigliardi
    """Check if in there is at disk of the given type in the configuration.
442 51cb1581 Luca Bigliardi

443 cd3b4ff4 Helga Velroyen
    @type dev_type: L{constants.DTS_BLOCK}
444 51cb1581 Luca Bigliardi
    @param dev_type: the type to look for
445 51cb1581 Luca Bigliardi
    @rtype: boolean
446 51cb1581 Luca Bigliardi
    @return: boolean indicating if a disk of the given type was found or not
447 51cb1581 Luca Bigliardi

448 51cb1581 Luca Bigliardi
    """
449 51cb1581 Luca Bigliardi
    for instance in self.instances.values():
450 51cb1581 Luca Bigliardi
      for disk in instance.disks:
451 51cb1581 Luca Bigliardi
        if disk.IsBasedOnDiskType(dev_type):
452 51cb1581 Luca Bigliardi
          return True
453 51cb1581 Luca Bigliardi
    return False
454 51cb1581 Luca Bigliardi
455 90d726a8 Iustin Pop
  def UpgradeConfig(self):
456 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
457 90d726a8 Iustin Pop

458 90d726a8 Iustin Pop
    """
459 90d726a8 Iustin Pop
    self.cluster.UpgradeConfig()
460 90d726a8 Iustin Pop
    for node in self.nodes.values():
461 90d726a8 Iustin Pop
      node.UpgradeConfig()
462 90d726a8 Iustin Pop
    for instance in self.instances.values():
463 90d726a8 Iustin Pop
      instance.UpgradeConfig()
464 a2112db5 Helga Velroyen
    self._UpgradeEnabledDiskTemplates()
465 3df43542 Guido Trotter
    if self.nodegroups is None:
466 3df43542 Guido Trotter
      self.nodegroups = {}
467 3df43542 Guido Trotter
    for nodegroup in self.nodegroups.values():
468 3df43542 Guido Trotter
      nodegroup.UpgradeConfig()
469 a2112db5 Helga Velroyen
      InstancePolicy.UpgradeDiskTemplates(
470 a2112db5 Helga Velroyen
        nodegroup.ipolicy, self.cluster.enabled_disk_templates)
471 ee2f0ed4 Luca Bigliardi
    if self.cluster.drbd_usermode_helper is None:
472 25e5e785 Helga Velroyen
      if self.cluster.IsDiskTemplateEnabled(constants.DT_DRBD8):
473 ee2f0ed4 Luca Bigliardi
        self.cluster.drbd_usermode_helper = constants.DEFAULT_DRBD_HELPER
474 eaa4c57c Dimitris Aragiorgis
    if self.networks is None:
475 eaa4c57c Dimitris Aragiorgis
      self.networks = {}
476 ee9516c8 Guido Trotter
    for network in self.networks.values():
477 ee9516c8 Guido Trotter
      network.UpgradeConfig()
478 c66d8987 Helga Velroyen
479 1b02d7ef Helga Velroyen
  def _UpgradeEnabledDiskTemplates(self):
480 1b02d7ef Helga Velroyen
    """Upgrade the cluster's enabled disk templates by inspecting the currently
481 1b02d7ef Helga Velroyen
       enabled and/or used disk templates.
482 c66d8987 Helga Velroyen

483 c66d8987 Helga Velroyen
    """
484 1b02d7ef Helga Velroyen
    if not self.cluster.enabled_disk_templates:
485 1b02d7ef Helga Velroyen
      template_set = \
486 1b02d7ef Helga Velroyen
        set([inst.disk_template for inst in self.instances.values()])
487 1b02d7ef Helga Velroyen
      # Add drbd and plain, if lvm is enabled (by specifying a volume group)
488 c66d8987 Helga Velroyen
      if self.cluster.volume_group_name:
489 1b02d7ef Helga Velroyen
        template_set.add(constants.DT_DRBD8)
490 1b02d7ef Helga Velroyen
        template_set.add(constants.DT_PLAIN)
491 1b02d7ef Helga Velroyen
      # Set enabled_disk_templates to the inferred disk templates. Order them
492 c66d8987 Helga Velroyen
      # according to a preference list that is based on Ganeti's history of
493 1b02d7ef Helga Velroyen
      # supported disk templates.
494 1b02d7ef Helga Velroyen
      self.cluster.enabled_disk_templates = []
495 1b02d7ef Helga Velroyen
      for preferred_template in constants.DISK_TEMPLATE_PREFERENCE:
496 1b02d7ef Helga Velroyen
        if preferred_template in template_set:
497 1b02d7ef Helga Velroyen
          self.cluster.enabled_disk_templates.append(preferred_template)
498 1b02d7ef Helga Velroyen
          template_set.remove(preferred_template)
499 1b02d7ef Helga Velroyen
      self.cluster.enabled_disk_templates.extend(list(template_set))
500 a2112db5 Helga Velroyen
    InstancePolicy.UpgradeDiskTemplates(
501 a2112db5 Helga Velroyen
      self.cluster.ipolicy, self.cluster.enabled_disk_templates)
502 90d726a8 Iustin Pop
503 a8083063 Iustin Pop
504 a8083063 Iustin Pop
class NIC(ConfigObject):
505 a8083063 Iustin Pop
  """Config object representing a network card."""
506 9569d877 Dimitris Aragiorgis
  __slots__ = ["name", "mac", "ip", "network",
507 9569d877 Dimitris Aragiorgis
               "nicparams", "netinfo", "pci"] + _UUID
508 a8083063 Iustin Pop
509 255e19d4 Guido Trotter
  @classmethod
510 255e19d4 Guido Trotter
  def CheckParameterSyntax(cls, nicparams):
511 255e19d4 Guido Trotter
    """Check the given parameters for validity.
512 255e19d4 Guido Trotter

513 255e19d4 Guido Trotter
    @type nicparams:  dict
514 255e19d4 Guido Trotter
    @param nicparams: dictionary with parameter names/value
515 255e19d4 Guido Trotter
    @raise errors.ConfigurationError: when a parameter is not valid
516 255e19d4 Guido Trotter

517 255e19d4 Guido Trotter
    """
518 53258324 Michael Hanselmann
    mode = nicparams[constants.NIC_MODE]
519 53258324 Michael Hanselmann
    if (mode not in constants.NIC_VALID_MODES and
520 53258324 Michael Hanselmann
        mode != constants.VALUE_AUTO):
521 53258324 Michael Hanselmann
      raise errors.ConfigurationError("Invalid NIC mode '%s'" % mode)
522 255e19d4 Guido Trotter
523 53258324 Michael Hanselmann
    if (mode == constants.NIC_MODE_BRIDGED and
524 255e19d4 Guido Trotter
        not nicparams[constants.NIC_LINK]):
525 53258324 Michael Hanselmann
      raise errors.ConfigurationError("Missing bridged NIC link")
526 255e19d4 Guido Trotter
527 a8083063 Iustin Pop
528 a8083063 Iustin Pop
class Disk(ConfigObject):
529 a8083063 Iustin Pop
  """Config object representing a block device."""
530 a57e502a Thomas Thrainer
  __slots__ = (["name", "dev_type", "logical_id", "children", "iv_name",
531 9569d877 Dimitris Aragiorgis
                "size", "mode", "params", "spindles", "pci"] + _UUID +
532 0c3d9c7c Thomas Thrainer
               # dynamic_params is special. It depends on the node this instance
533 0c3d9c7c Thomas Thrainer
               # is sent to, and should not be persisted.
534 0c3d9c7c Thomas Thrainer
               ["dynamic_params"])
535 a8083063 Iustin Pop
536 a8083063 Iustin Pop
  def CreateOnSecondary(self):
537 a8083063 Iustin Pop
    """Test if this device needs to be created on a secondary node."""
538 cd3b4ff4 Helga Velroyen
    return self.dev_type in (constants.DT_DRBD8, constants.DT_PLAIN)
539 a8083063 Iustin Pop
540 a8083063 Iustin Pop
  def AssembleOnSecondary(self):
541 a8083063 Iustin Pop
    """Test if this device needs to be assembled on a secondary node."""
542 cd3b4ff4 Helga Velroyen
    return self.dev_type in (constants.DT_DRBD8, constants.DT_PLAIN)
543 a8083063 Iustin Pop
544 a8083063 Iustin Pop
  def OpenOnSecondary(self):
545 a8083063 Iustin Pop
    """Test if this device needs to be opened on a secondary node."""
546 cd3b4ff4 Helga Velroyen
    return self.dev_type in (constants.DT_PLAIN,)
547 a8083063 Iustin Pop
548 222f2dd5 Iustin Pop
  def StaticDevPath(self):
549 222f2dd5 Iustin Pop
    """Return the device path if this device type has a static one.
550 222f2dd5 Iustin Pop

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

555 e51db2a6 Iustin Pop
    @warning: The path returned is not a normalized pathname; callers
556 e51db2a6 Iustin Pop
        should check that it is a valid path.
557 e51db2a6 Iustin Pop

558 222f2dd5 Iustin Pop
    """
559 cd3b4ff4 Helga Velroyen
    if self.dev_type == constants.DT_PLAIN:
560 222f2dd5 Iustin Pop
      return "/dev/%s/%s" % (self.logical_id[0], self.logical_id[1])
561 cd3b4ff4 Helga Velroyen
    elif self.dev_type == constants.DT_BLOCK:
562 b6135bbc Apollon Oikonomopoulos
      return self.logical_id[1]
563 cd3b4ff4 Helga Velroyen
    elif self.dev_type == constants.DT_RBD:
564 7181fba0 Constantinos Venetsanopoulos
      return "/dev/%s/%s" % (self.logical_id[0], self.logical_id[1])
565 222f2dd5 Iustin Pop
    return None
566 222f2dd5 Iustin Pop
567 fc1dc9d7 Iustin Pop
  def ChildrenNeeded(self):
568 fc1dc9d7 Iustin Pop
    """Compute the needed number of children for activation.
569 fc1dc9d7 Iustin Pop

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

574 fc1dc9d7 Iustin Pop
    Currently, only DRBD8 supports diskless activation (therefore we
575 fc1dc9d7 Iustin Pop
    return 0), for all other we keep the previous semantics and return
576 fc1dc9d7 Iustin Pop
    -1.
577 fc1dc9d7 Iustin Pop

578 fc1dc9d7 Iustin Pop
    """
579 cd3b4ff4 Helga Velroyen
    if self.dev_type == constants.DT_DRBD8:
580 fc1dc9d7 Iustin Pop
      return 0
581 fc1dc9d7 Iustin Pop
    return -1
582 fc1dc9d7 Iustin Pop
583 51cb1581 Luca Bigliardi
  def IsBasedOnDiskType(self, dev_type):
584 51cb1581 Luca Bigliardi
    """Check if the disk or its children are based on the given type.
585 51cb1581 Luca Bigliardi

586 cd3b4ff4 Helga Velroyen
    @type dev_type: L{constants.DTS_BLOCK}
587 51cb1581 Luca Bigliardi
    @param dev_type: the type to look for
588 51cb1581 Luca Bigliardi
    @rtype: boolean
589 51cb1581 Luca Bigliardi
    @return: boolean indicating if a device of the given type was found or not
590 51cb1581 Luca Bigliardi

591 51cb1581 Luca Bigliardi
    """
592 51cb1581 Luca Bigliardi
    if self.children:
593 51cb1581 Luca Bigliardi
      for child in self.children:
594 51cb1581 Luca Bigliardi
        if child.IsBasedOnDiskType(dev_type):
595 51cb1581 Luca Bigliardi
          return True
596 51cb1581 Luca Bigliardi
    return self.dev_type == dev_type
597 51cb1581 Luca Bigliardi
598 1c3231aa Thomas Thrainer
  def GetNodes(self, node_uuid):
599 a8083063 Iustin Pop
    """This function returns the nodes this device lives on.
600 a8083063 Iustin Pop

601 a8083063 Iustin Pop
    Given the node on which the parent of the device lives on (or, in
602 a8083063 Iustin Pop
    case of a top-level device, the primary node of the devices'
603 a8083063 Iustin Pop
    instance), this function will return a list of nodes on which this
604 a8083063 Iustin Pop
    devices needs to (or can) be assembled.
605 a8083063 Iustin Pop

606 a8083063 Iustin Pop
    """
607 cd3b4ff4 Helga Velroyen
    if self.dev_type in [constants.DT_PLAIN, constants.DT_FILE,
608 cd3b4ff4 Helga Velroyen
                         constants.DT_BLOCK, constants.DT_RBD,
609 8106dd64 Santi Raffa
                         constants.DT_EXT, constants.DT_SHARED_FILE,
610 8106dd64 Santi Raffa
                         constants.DT_GLUSTER]:
611 1c3231aa Thomas Thrainer
      result = [node_uuid]
612 66a37e7a Helga Velroyen
    elif self.dev_type in constants.DTS_DRBD:
613 a8083063 Iustin Pop
      result = [self.logical_id[0], self.logical_id[1]]
614 1c3231aa Thomas Thrainer
      if node_uuid not in result:
615 3ecf6786 Iustin Pop
        raise errors.ConfigurationError("DRBD device passed unknown node")
616 a8083063 Iustin Pop
    else:
617 3ecf6786 Iustin Pop
      raise errors.ProgrammerError("Unhandled device type %s" % self.dev_type)
618 a8083063 Iustin Pop
    return result
619 a8083063 Iustin Pop
620 1c3231aa Thomas Thrainer
  def ComputeNodeTree(self, parent_node_uuid):
621 a8083063 Iustin Pop
    """Compute the node/disk tree for this disk and its children.
622 a8083063 Iustin Pop

623 a8083063 Iustin Pop
    This method, given the node on which the parent disk lives, will
624 1c3231aa Thomas Thrainer
    return the list of all (node UUID, disk) pairs which describe the disk
625 abdf0113 Iustin Pop
    tree in the most compact way. For example, a drbd/lvm stack
626 abdf0113 Iustin Pop
    will be returned as (primary_node, drbd) and (secondary_node, drbd)
627 abdf0113 Iustin Pop
    which represents all the top-level devices on the nodes.
628 a8083063 Iustin Pop

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

658 6d33a6eb Iustin Pop
    This only works for VG-based disks.
659 6d33a6eb Iustin Pop

660 6d33a6eb Iustin Pop
    @type amount: integer
661 6d33a6eb Iustin Pop
    @param amount: the desired increase in (user-visible) disk space
662 6d33a6eb Iustin Pop
    @rtype: dict
663 6d33a6eb Iustin Pop
    @return: a dictionary of volume-groups and the required size
664 6d33a6eb Iustin Pop

665 6d33a6eb Iustin Pop
    """
666 cd3b4ff4 Helga Velroyen
    if self.dev_type == constants.DT_PLAIN:
667 6d33a6eb Iustin Pop
      return {self.logical_id[0]: amount}
668 cd3b4ff4 Helga Velroyen
    elif self.dev_type == constants.DT_DRBD8:
669 6d33a6eb Iustin Pop
      if self.children:
670 6d33a6eb Iustin Pop
        return self.children[0].ComputeGrowth(amount)
671 6d33a6eb Iustin Pop
      else:
672 6d33a6eb Iustin Pop
        return {}
673 6d33a6eb Iustin Pop
    else:
674 6d33a6eb Iustin Pop
      # Other disk types do not require VG space
675 6d33a6eb Iustin Pop
      return {}
676 6d33a6eb Iustin Pop
677 acec9d51 Iustin Pop
  def RecordGrow(self, amount):
678 acec9d51 Iustin Pop
    """Update the size of this disk after growth.
679 acec9d51 Iustin Pop

680 acec9d51 Iustin Pop
    This method recurses over the disks's children and updates their
681 acec9d51 Iustin Pop
    size correspondigly. The method needs to be kept in sync with the
682 acec9d51 Iustin Pop
    actual algorithms from bdev.
683 acec9d51 Iustin Pop

684 acec9d51 Iustin Pop
    """
685 cd3b4ff4 Helga Velroyen
    if self.dev_type in (constants.DT_PLAIN, constants.DT_FILE,
686 cd3b4ff4 Helga Velroyen
                         constants.DT_RBD, constants.DT_EXT,
687 8106dd64 Santi Raffa
                         constants.DT_SHARED_FILE, constants.DT_GLUSTER):
688 acec9d51 Iustin Pop
      self.size += amount
689 cd3b4ff4 Helga Velroyen
    elif self.dev_type == constants.DT_DRBD8:
690 acec9d51 Iustin Pop
      if self.children:
691 acec9d51 Iustin Pop
        self.children[0].RecordGrow(amount)
692 acec9d51 Iustin Pop
      self.size += amount
693 acec9d51 Iustin Pop
    else:
694 acec9d51 Iustin Pop
      raise errors.ProgrammerError("Disk.RecordGrow called for unsupported"
695 acec9d51 Iustin Pop
                                   " disk type %s" % self.dev_type)
696 acec9d51 Iustin Pop
697 b54ecf12 Bernardo Dal Seno
  def Update(self, size=None, mode=None, spindles=None):
698 b54ecf12 Bernardo Dal Seno
    """Apply changes to size, spindles and mode.
699 735e1318 Michael Hanselmann

700 735e1318 Michael Hanselmann
    """
701 cd3b4ff4 Helga Velroyen
    if self.dev_type == constants.DT_DRBD8:
702 735e1318 Michael Hanselmann
      if self.children:
703 735e1318 Michael Hanselmann
        self.children[0].Update(size=size, mode=mode)
704 735e1318 Michael Hanselmann
    else:
705 735e1318 Michael Hanselmann
      assert not self.children
706 735e1318 Michael Hanselmann
707 735e1318 Michael Hanselmann
    if size is not None:
708 735e1318 Michael Hanselmann
      self.size = size
709 735e1318 Michael Hanselmann
    if mode is not None:
710 735e1318 Michael Hanselmann
      self.mode = mode
711 b54ecf12 Bernardo Dal Seno
    if spindles is not None:
712 b54ecf12 Bernardo Dal Seno
      self.spindles = spindles
713 735e1318 Michael Hanselmann
714 a805ec18 Iustin Pop
  def UnsetSize(self):
715 a805ec18 Iustin Pop
    """Sets recursively the size to zero for the disk and its children.
716 a805ec18 Iustin Pop

717 a805ec18 Iustin Pop
    """
718 a805ec18 Iustin Pop
    if self.children:
719 a805ec18 Iustin Pop
      for child in self.children:
720 a805ec18 Iustin Pop
        child.UnsetSize()
721 a805ec18 Iustin Pop
    self.size = 0
722 a805ec18 Iustin Pop
723 0c3d9c7c Thomas Thrainer
  def UpdateDynamicDiskParams(self, target_node_uuid, nodes_ip):
724 0c3d9c7c Thomas Thrainer
    """Updates the dynamic disk params for the given node.
725 0402302c Iustin Pop

726 0c3d9c7c Thomas Thrainer
    This is mainly used for drbd, which needs ip/port configuration.
727 0402302c Iustin Pop

728 0402302c Iustin Pop
    Arguments:
729 1c3231aa Thomas Thrainer
      - target_node_uuid: the node UUID we wish to configure for
730 0402302c Iustin Pop
      - nodes_ip: a mapping of node name to ip
731 0402302c Iustin Pop

732 0c3d9c7c Thomas Thrainer
    The target_node must exist in nodes_ip, and should be one of the
733 0c3d9c7c Thomas Thrainer
    nodes in the logical ID if this device is a DRBD device.
734 0402302c Iustin Pop

735 0402302c Iustin Pop
    """
736 0402302c Iustin Pop
    if self.children:
737 0402302c Iustin Pop
      for child in self.children:
738 0c3d9c7c Thomas Thrainer
        child.UpdateDynamicDiskParams(target_node_uuid, nodes_ip)
739 0402302c Iustin Pop
740 0c3d9c7c Thomas Thrainer
    dyn_disk_params = {}
741 e8c86ab1 Klaus Aehlig
    if self.logical_id is not None and self.dev_type in constants.DTS_DRBD:
742 0c3d9c7c Thomas Thrainer
      pnode_uuid, snode_uuid, _, pminor, sminor, _ = self.logical_id
743 1c3231aa Thomas Thrainer
      if target_node_uuid not in (pnode_uuid, snode_uuid):
744 0c3d9c7c Thomas Thrainer
        # disk object is being sent to neither the primary nor the secondary
745 0c3d9c7c Thomas Thrainer
        # node. reset the dynamic parameters, the target node is not
746 0c3d9c7c Thomas Thrainer
        # supposed to use them.
747 0c3d9c7c Thomas Thrainer
        self.dynamic_params = dyn_disk_params
748 0c3d9c7c Thomas Thrainer
        return
749 0c3d9c7c Thomas Thrainer
750 1c3231aa Thomas Thrainer
      pnode_ip = nodes_ip.get(pnode_uuid, None)
751 1c3231aa Thomas Thrainer
      snode_ip = nodes_ip.get(snode_uuid, None)
752 0402302c Iustin Pop
      if pnode_ip is None or snode_ip is None:
753 0402302c Iustin Pop
        raise errors.ConfigurationError("Can't find primary or secondary node"
754 0402302c Iustin Pop
                                        " for %s" % str(self))
755 1c3231aa Thomas Thrainer
      if pnode_uuid == target_node_uuid:
756 0c3d9c7c Thomas Thrainer
        dyn_disk_params[constants.DDP_LOCAL_IP] = pnode_ip
757 0c3d9c7c Thomas Thrainer
        dyn_disk_params[constants.DDP_REMOTE_IP] = snode_ip
758 0c3d9c7c Thomas Thrainer
        dyn_disk_params[constants.DDP_LOCAL_MINOR] = pminor
759 0c3d9c7c Thomas Thrainer
        dyn_disk_params[constants.DDP_REMOTE_MINOR] = sminor
760 0402302c Iustin Pop
      else: # it must be secondary, we tested above
761 0c3d9c7c Thomas Thrainer
        dyn_disk_params[constants.DDP_LOCAL_IP] = snode_ip
762 0c3d9c7c Thomas Thrainer
        dyn_disk_params[constants.DDP_REMOTE_IP] = pnode_ip
763 0c3d9c7c Thomas Thrainer
        dyn_disk_params[constants.DDP_LOCAL_MINOR] = sminor
764 0c3d9c7c Thomas Thrainer
        dyn_disk_params[constants.DDP_REMOTE_MINOR] = pminor
765 0c3d9c7c Thomas Thrainer
766 0c3d9c7c Thomas Thrainer
    self.dynamic_params = dyn_disk_params
767 0402302c Iustin Pop
768 a0d2a91e Thomas Thrainer
  # pylint: disable=W0221
769 a5efec93 Santi Raffa
  def ToDict(self, include_dynamic_params=False,
770 a5efec93 Santi Raffa
             _with_private=False):
771 ff9c047c Iustin Pop
    """Disk-specific conversion to standard python types.
772 ff9c047c Iustin Pop

773 ff9c047c Iustin Pop
    This replaces the children lists of objects with lists of
774 ff9c047c Iustin Pop
    standard python types.
775 ff9c047c Iustin Pop

776 ff9c047c Iustin Pop
    """
777 ff9c047c Iustin Pop
    bo = super(Disk, self).ToDict()
778 a0d2a91e Thomas Thrainer
    if not include_dynamic_params and "dynamic_params" in bo:
779 a0d2a91e Thomas Thrainer
      del bo["dynamic_params"]
780 ff9c047c Iustin Pop
781 ff9c047c Iustin Pop
    for attr in ("children",):
782 ff9c047c Iustin Pop
      alist = bo.get(attr, None)
783 ff9c047c Iustin Pop
      if alist:
784 fe502d25 Iustin Pop
        bo[attr] = outils.ContainerToDicts(alist)
785 ff9c047c Iustin Pop
    return bo
786 ff9c047c Iustin Pop
787 ff9c047c Iustin Pop
  @classmethod
788 ff9c047c Iustin Pop
  def FromDict(cls, val):
789 ff9c047c Iustin Pop
    """Custom function for Disks
790 ff9c047c Iustin Pop

791 ff9c047c Iustin Pop
    """
792 ff9c047c Iustin Pop
    obj = super(Disk, cls).FromDict(val)
793 ff9c047c Iustin Pop
    if obj.children:
794 fe502d25 Iustin Pop
      obj.children = outils.ContainerFromDicts(obj.children, list, Disk)
795 ff9c047c Iustin Pop
    if obj.logical_id and isinstance(obj.logical_id, list):
796 ff9c047c Iustin Pop
      obj.logical_id = tuple(obj.logical_id)
797 66a37e7a Helga Velroyen
    if obj.dev_type in constants.DTS_DRBD:
798 f9518d38 Iustin Pop
      # we need a tuple of length six here
799 f9518d38 Iustin Pop
      if len(obj.logical_id) < 6:
800 f9518d38 Iustin Pop
        obj.logical_id += (None,) * (6 - len(obj.logical_id))
801 ff9c047c Iustin Pop
    return obj
802 ff9c047c Iustin Pop
803 65a15336 Iustin Pop
  def __str__(self):
804 65a15336 Iustin Pop
    """Custom str() formatter for disks.
805 65a15336 Iustin Pop

806 65a15336 Iustin Pop
    """
807 cd3b4ff4 Helga Velroyen
    if self.dev_type == constants.DT_PLAIN:
808 e687ec01 Michael Hanselmann
      val = "<LogicalVolume(/dev/%s/%s" % self.logical_id
809 66a37e7a Helga Velroyen
    elif self.dev_type in constants.DTS_DRBD:
810 89f28b76 Iustin Pop
      node_a, node_b, port, minor_a, minor_b = self.logical_id[:5]
811 00fb8246 Michael Hanselmann
      val = "<DRBD8("
812 073ca59e Iustin Pop
813 a57e502a Thomas Thrainer
      val += ("hosts=%s/%d-%s/%d, port=%s, " %
814 a57e502a Thomas Thrainer
              (node_a, minor_a, node_b, minor_b, port))
815 65a15336 Iustin Pop
      if self.children and self.children.count(None) == 0:
816 65a15336 Iustin Pop
        val += "backend=%s, metadev=%s" % (self.children[0], self.children[1])
817 65a15336 Iustin Pop
      else:
818 65a15336 Iustin Pop
        val += "no local storage"
819 65a15336 Iustin Pop
    else:
820 a57e502a Thomas Thrainer
      val = ("<Disk(type=%s, logical_id=%s, children=%s" %
821 a57e502a Thomas Thrainer
             (self.dev_type, self.logical_id, self.children))
822 65a15336 Iustin Pop
    if self.iv_name is None:
823 65a15336 Iustin Pop
      val += ", not visible"
824 65a15336 Iustin Pop
    else:
825 65a15336 Iustin Pop
      val += ", visible as /dev/%s" % self.iv_name
826 b54ecf12 Bernardo Dal Seno
    if self.spindles is not None:
827 b54ecf12 Bernardo Dal Seno
      val += ", spindles=%s" % self.spindles
828 fd965830 Iustin Pop
    if isinstance(self.size, int):
829 fd965830 Iustin Pop
      val += ", size=%dm)>" % self.size
830 fd965830 Iustin Pop
    else:
831 fd965830 Iustin Pop
      val += ", size='%s')>" % (self.size,)
832 65a15336 Iustin Pop
    return val
833 65a15336 Iustin Pop
834 332d0e37 Iustin Pop
  def Verify(self):
835 332d0e37 Iustin Pop
    """Checks that this disk is correctly configured.
836 332d0e37 Iustin Pop

837 332d0e37 Iustin Pop
    """
838 7c4d6c7b Michael Hanselmann
    all_errors = []
839 332d0e37 Iustin Pop
    if self.mode not in constants.DISK_ACCESS_SET:
840 7c4d6c7b Michael Hanselmann
      all_errors.append("Disk access mode '%s' is invalid" % (self.mode, ))
841 7c4d6c7b Michael Hanselmann
    return all_errors
842 332d0e37 Iustin Pop
843 90d726a8 Iustin Pop
  def UpgradeConfig(self):
844 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
845 90d726a8 Iustin Pop

846 90d726a8 Iustin Pop
    """
847 90d726a8 Iustin Pop
    if self.children:
848 90d726a8 Iustin Pop
      for child in self.children:
849 90d726a8 Iustin Pop
        child.UpgradeConfig()
850 bc5d0215 Andrea Spadaccini
851 cce46164 Renรฉ Nussbaumer
    # FIXME: Make this configurable in Ganeti 2.7
852 54666867 Dimitris Aragiorgis
    # Params should be an empty dict that gets filled any time needed
853 54666867 Dimitris Aragiorgis
    # In case of ext template we allow arbitrary params that should not
854 54666867 Dimitris Aragiorgis
    # be overrided during a config reload/upgrade.
855 54666867 Dimitris Aragiorgis
    if not self.params or not isinstance(self.params, dict):
856 54666867 Dimitris Aragiorgis
      self.params = {}
857 54666867 Dimitris Aragiorgis
858 90d726a8 Iustin Pop
    # add here config upgrade for this disk
859 90d726a8 Iustin Pop
860 73d6b4a7 Helga Velroyen
    # map of legacy device types (mapping differing LD constants to new
861 73d6b4a7 Helga Velroyen
    # DT constants)
862 73d6b4a7 Helga Velroyen
    LEG_DEV_TYPE_MAP = {"lvm": constants.DT_PLAIN, "drbd8": constants.DT_DRBD8}
863 73d6b4a7 Helga Velroyen
    if self.dev_type in LEG_DEV_TYPE_MAP:
864 73d6b4a7 Helga Velroyen
      self.dev_type = LEG_DEV_TYPE_MAP[self.dev_type]
865 73d6b4a7 Helga Velroyen
866 cd46491f Renรฉ Nussbaumer
  @staticmethod
867 cd46491f Renรฉ Nussbaumer
  def ComputeLDParams(disk_template, disk_params):
868 cd46491f Renรฉ Nussbaumer
    """Computes Logical Disk parameters from Disk Template parameters.
869 cd46491f Renรฉ Nussbaumer

870 cd46491f Renรฉ Nussbaumer
    @type disk_template: string
871 cd46491f Renรฉ Nussbaumer
    @param disk_template: disk template, one of L{constants.DISK_TEMPLATES}
872 cd46491f Renรฉ Nussbaumer
    @type disk_params: dict
873 cd46491f Renรฉ Nussbaumer
    @param disk_params: disk template parameters;
874 cd46491f Renรฉ Nussbaumer
                        dict(template_name -> parameters
875 cd46491f Renรฉ Nussbaumer
    @rtype: list(dict)
876 cd46491f Renรฉ Nussbaumer
    @return: a list of dicts, one for each node of the disk hierarchy. Each dict
877 cd46491f Renรฉ Nussbaumer
      contains the LD parameters of the node. The tree is flattened in-order.
878 cd46491f Renรฉ Nussbaumer

879 cd46491f Renรฉ Nussbaumer
    """
880 cd46491f Renรฉ Nussbaumer
    if disk_template not in constants.DISK_TEMPLATES:
881 cd46491f Renรฉ Nussbaumer
      raise errors.ProgrammerError("Unknown disk template %s" % disk_template)
882 cd46491f Renรฉ Nussbaumer
883 cd46491f Renรฉ Nussbaumer
    assert disk_template in disk_params
884 cd46491f Renรฉ Nussbaumer
885 cd46491f Renรฉ Nussbaumer
    result = list()
886 cd46491f Renรฉ Nussbaumer
    dt_params = disk_params[disk_template]
887 3fffa0c6 Santi Raffa
888 cd46491f Renรฉ Nussbaumer
    if disk_template == constants.DT_DRBD8:
889 6da90c0a Helga Velroyen
      result.append(FillDict(constants.DISK_LD_DEFAULTS[constants.DT_DRBD8], {
890 cd46491f Renรฉ Nussbaumer
        constants.LDP_RESYNC_RATE: dt_params[constants.DRBD_RESYNC_RATE],
891 cd46491f Renรฉ Nussbaumer
        constants.LDP_BARRIERS: dt_params[constants.DRBD_DISK_BARRIERS],
892 cd46491f Renรฉ Nussbaumer
        constants.LDP_NO_META_FLUSH: dt_params[constants.DRBD_META_BARRIERS],
893 cd46491f Renรฉ Nussbaumer
        constants.LDP_DEFAULT_METAVG: dt_params[constants.DRBD_DEFAULT_METAVG],
894 cd46491f Renรฉ Nussbaumer
        constants.LDP_DISK_CUSTOM: dt_params[constants.DRBD_DISK_CUSTOM],
895 cd46491f Renรฉ Nussbaumer
        constants.LDP_NET_CUSTOM: dt_params[constants.DRBD_NET_CUSTOM],
896 65fc2388 Thomas Thrainer
        constants.LDP_PROTOCOL: dt_params[constants.DRBD_PROTOCOL],
897 cd46491f Renรฉ Nussbaumer
        constants.LDP_DYNAMIC_RESYNC: dt_params[constants.DRBD_DYNAMIC_RESYNC],
898 cd46491f Renรฉ Nussbaumer
        constants.LDP_PLAN_AHEAD: dt_params[constants.DRBD_PLAN_AHEAD],
899 cd46491f Renรฉ Nussbaumer
        constants.LDP_FILL_TARGET: dt_params[constants.DRBD_FILL_TARGET],
900 cd46491f Renรฉ Nussbaumer
        constants.LDP_DELAY_TARGET: dt_params[constants.DRBD_DELAY_TARGET],
901 cd46491f Renรฉ Nussbaumer
        constants.LDP_MAX_RATE: dt_params[constants.DRBD_MAX_RATE],
902 cd46491f Renรฉ Nussbaumer
        constants.LDP_MIN_RATE: dt_params[constants.DRBD_MIN_RATE],
903 52f93ffd Michael Hanselmann
        }))
904 cd46491f Renรฉ Nussbaumer
905 cd46491f Renรฉ Nussbaumer
      # data LV
906 6da90c0a Helga Velroyen
      result.append(FillDict(constants.DISK_LD_DEFAULTS[constants.DT_PLAIN], {
907 cd46491f Renรฉ Nussbaumer
        constants.LDP_STRIPES: dt_params[constants.DRBD_DATA_STRIPES],
908 52f93ffd Michael Hanselmann
        }))
909 cd46491f Renรฉ Nussbaumer
910 cd46491f Renรฉ Nussbaumer
      # metadata LV
911 6da90c0a Helga Velroyen
      result.append(FillDict(constants.DISK_LD_DEFAULTS[constants.DT_PLAIN], {
912 cd46491f Renรฉ Nussbaumer
        constants.LDP_STRIPES: dt_params[constants.DRBD_META_STRIPES],
913 52f93ffd Michael Hanselmann
        }))
914 52f93ffd Michael Hanselmann
915 3fffa0c6 Santi Raffa
    else:
916 3fffa0c6 Santi Raffa
      defaults = constants.DISK_LD_DEFAULTS[disk_template]
917 3fffa0c6 Santi Raffa
      values = {}
918 3fffa0c6 Santi Raffa
      for field in defaults:
919 3fffa0c6 Santi Raffa
        values[field] = dt_params[field]
920 3fffa0c6 Santi Raffa
      result.append(FillDict(defaults, values))
921 938adc87 Constantinos Venetsanopoulos
922 cd46491f Renรฉ Nussbaumer
    return result
923 cd46491f Renรฉ Nussbaumer
924 a8083063 Iustin Pop
925 918eb80b Agata Murawska
class InstancePolicy(ConfigObject):
926 ffa339ca Iustin Pop
  """Config object representing instance policy limits dictionary.
927 918eb80b Agata Murawska

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

931 ffa339ca Iustin Pop
  """
932 918eb80b Agata Murawska
  @classmethod
933 a2112db5 Helga Velroyen
  def UpgradeDiskTemplates(cls, ipolicy, enabled_disk_templates):
934 a2112db5 Helga Velroyen
    """Upgrades the ipolicy configuration."""
935 a2112db5 Helga Velroyen
    if constants.IPOLICY_DTS in ipolicy:
936 a2112db5 Helga Velroyen
      if not set(ipolicy[constants.IPOLICY_DTS]).issubset(
937 a2112db5 Helga Velroyen
        set(enabled_disk_templates)):
938 a2112db5 Helga Velroyen
        ipolicy[constants.IPOLICY_DTS] = list(
939 a2112db5 Helga Velroyen
          set(ipolicy[constants.IPOLICY_DTS]) & set(enabled_disk_templates))
940 a2112db5 Helga Velroyen
941 a2112db5 Helga Velroyen
  @classmethod
942 8b057218 Renรฉ Nussbaumer
  def CheckParameterSyntax(cls, ipolicy, check_std):
943 918eb80b Agata Murawska
    """ Check the instance policy for validity.
944 918eb80b Agata Murawska

945 da5f09ef Bernardo Dal Seno
    @type ipolicy: dict
946 da5f09ef Bernardo Dal Seno
    @param ipolicy: dictionary with min/max/std specs and policies
947 da5f09ef Bernardo Dal Seno
    @type check_std: bool
948 da5f09ef Bernardo Dal Seno
    @param check_std: Whether to check std value or just assume compliance
949 da5f09ef Bernardo Dal Seno
    @raise errors.ConfigurationError: when the policy is not legal
950 da5f09ef Bernardo Dal Seno

951 918eb80b Agata Murawska
    """
952 62fed51b Bernardo Dal Seno
    InstancePolicy.CheckISpecSyntax(ipolicy, check_std)
953 d04c9d45 Iustin Pop
    if constants.IPOLICY_DTS in ipolicy:
954 d04c9d45 Iustin Pop
      InstancePolicy.CheckDiskTemplates(ipolicy[constants.IPOLICY_DTS])
955 ff6c5e55 Iustin Pop
    for key in constants.IPOLICY_PARAMETERS:
956 ff6c5e55 Iustin Pop
      if key in ipolicy:
957 ff6c5e55 Iustin Pop
        InstancePolicy.CheckParameter(key, ipolicy[key])
958 57dc299a Iustin Pop
    wrong_keys = frozenset(ipolicy.keys()) - constants.IPOLICY_ALL_KEYS
959 57dc299a Iustin Pop
    if wrong_keys:
960 57dc299a Iustin Pop
      raise errors.ConfigurationError("Invalid keys in ipolicy: %s" %
961 57dc299a Iustin Pop
                                      utils.CommaJoin(wrong_keys))
962 918eb80b Agata Murawska
963 918eb80b Agata Murawska
  @classmethod
964 0f511c8a Bernardo Dal Seno
  def _CheckIncompleteSpec(cls, spec, keyname):
965 0f511c8a Bernardo Dal Seno
    missing_params = constants.ISPECS_PARAMETERS - frozenset(spec.keys())
966 0f511c8a Bernardo Dal Seno
    if missing_params:
967 0f511c8a Bernardo Dal Seno
      msg = ("Missing instance specs parameters for %s: %s" %
968 0f511c8a Bernardo Dal Seno
             (keyname, utils.CommaJoin(missing_params)))
969 0f511c8a Bernardo Dal Seno
      raise errors.ConfigurationError(msg)
970 0f511c8a Bernardo Dal Seno
971 0f511c8a Bernardo Dal Seno
  @classmethod
972 62fed51b Bernardo Dal Seno
  def CheckISpecSyntax(cls, ipolicy, check_std):
973 62fed51b Bernardo Dal Seno
    """Check the instance policy specs for validity.
974 62fed51b Bernardo Dal Seno

975 62fed51b Bernardo Dal Seno
    @type ipolicy: dict
976 62fed51b Bernardo Dal Seno
    @param ipolicy: dictionary with min/max/std specs
977 62fed51b Bernardo Dal Seno
    @type check_std: bool
978 62fed51b Bernardo Dal Seno
    @param check_std: Whether to check std value or just assume compliance
979 62fed51b Bernardo Dal Seno
    @raise errors.ConfigurationError: when specs are not valid
980 62fed51b Bernardo Dal Seno

981 62fed51b Bernardo Dal Seno
    """
982 62fed51b Bernardo Dal Seno
    if constants.ISPECS_MINMAX not in ipolicy:
983 62fed51b Bernardo Dal Seno
      # Nothing to check
984 62fed51b Bernardo Dal Seno
      return
985 62fed51b Bernardo Dal Seno
986 62fed51b Bernardo Dal Seno
    if check_std and constants.ISPECS_STD not in ipolicy:
987 62fed51b Bernardo Dal Seno
      msg = "Missing key in ipolicy: %s" % constants.ISPECS_STD
988 62fed51b Bernardo Dal Seno
      raise errors.ConfigurationError(msg)
989 62fed51b Bernardo Dal Seno
    stdspec = ipolicy.get(constants.ISPECS_STD)
990 b342c9dd Bernardo Dal Seno
    if check_std:
991 b342c9dd Bernardo Dal Seno
      InstancePolicy._CheckIncompleteSpec(stdspec, constants.ISPECS_STD)
992 b342c9dd Bernardo Dal Seno
993 41044e04 Bernardo Dal Seno
    if not ipolicy[constants.ISPECS_MINMAX]:
994 41044e04 Bernardo Dal Seno
      raise errors.ConfigurationError("Empty minmax specifications")
995 41044e04 Bernardo Dal Seno
    std_is_good = False
996 41044e04 Bernardo Dal Seno
    for minmaxspecs in ipolicy[constants.ISPECS_MINMAX]:
997 41044e04 Bernardo Dal Seno
      missing = constants.ISPECS_MINMAX_KEYS - frozenset(minmaxspecs.keys())
998 41044e04 Bernardo Dal Seno
      if missing:
999 41044e04 Bernardo Dal Seno
        msg = "Missing instance specification: %s" % utils.CommaJoin(missing)
1000 41044e04 Bernardo Dal Seno
        raise errors.ConfigurationError(msg)
1001 41044e04 Bernardo Dal Seno
      for (key, spec) in minmaxspecs.items():
1002 41044e04 Bernardo Dal Seno
        InstancePolicy._CheckIncompleteSpec(spec, key)
1003 41044e04 Bernardo Dal Seno
1004 41044e04 Bernardo Dal Seno
      spec_std_ok = True
1005 41044e04 Bernardo Dal Seno
      for param in constants.ISPECS_PARAMETERS:
1006 41044e04 Bernardo Dal Seno
        par_std_ok = InstancePolicy._CheckISpecParamSyntax(minmaxspecs, stdspec,
1007 41044e04 Bernardo Dal Seno
                                                           param, check_std)
1008 41044e04 Bernardo Dal Seno
        spec_std_ok = spec_std_ok and par_std_ok
1009 41044e04 Bernardo Dal Seno
      std_is_good = std_is_good or spec_std_ok
1010 41044e04 Bernardo Dal Seno
    if not std_is_good:
1011 b342c9dd Bernardo Dal Seno
      raise errors.ConfigurationError("Invalid std specifications")
1012 62fed51b Bernardo Dal Seno
1013 62fed51b Bernardo Dal Seno
  @classmethod
1014 62fed51b Bernardo Dal Seno
  def _CheckISpecParamSyntax(cls, minmaxspecs, stdspec, name, check_std):
1015 da5f09ef Bernardo Dal Seno
    """Check the instance policy specs for validity on a given key.
1016 918eb80b Agata Murawska

1017 da5f09ef Bernardo Dal Seno
    We check if the instance specs makes sense for a given key, that is
1018 da5f09ef Bernardo Dal Seno
    if minmaxspecs[min][name] <= stdspec[name] <= minmaxspec[max][name].
1019 918eb80b Agata Murawska

1020 da5f09ef Bernardo Dal Seno
    @type minmaxspecs: dict
1021 da5f09ef Bernardo Dal Seno
    @param minmaxspecs: dictionary with min and max instance spec
1022 da5f09ef Bernardo Dal Seno
    @type stdspec: dict
1023 da5f09ef Bernardo Dal Seno
    @param stdspec: dictionary with standard instance spec
1024 918eb80b Agata Murawska
    @type name: string
1025 918eb80b Agata Murawska
    @param name: what are the limits for
1026 8b057218 Renรฉ Nussbaumer
    @type check_std: bool
1027 8b057218 Renรฉ Nussbaumer
    @param check_std: Whether to check std value or just assume compliance
1028 b342c9dd Bernardo Dal Seno
    @rtype: bool
1029 b342c9dd Bernardo Dal Seno
    @return: C{True} when specs are valid, C{False} when standard spec for the
1030 b342c9dd Bernardo Dal Seno
        given name is not valid
1031 b342c9dd Bernardo Dal Seno
    @raise errors.ConfigurationError: when min/max specs for the given name
1032 b342c9dd Bernardo Dal Seno
        are not valid
1033 918eb80b Agata Murawska

1034 918eb80b Agata Murawska
    """
1035 da5f09ef Bernardo Dal Seno
    minspec = minmaxspecs[constants.ISPECS_MIN]
1036 da5f09ef Bernardo Dal Seno
    maxspec = minmaxspecs[constants.ISPECS_MAX]
1037 0f511c8a Bernardo Dal Seno
    min_v = minspec[name]
1038 b342c9dd Bernardo Dal Seno
    max_v = maxspec[name]
1039 8b057218 Renรฉ Nussbaumer
1040 b342c9dd Bernardo Dal Seno
    if min_v > max_v:
1041 b342c9dd Bernardo Dal Seno
      err = ("Invalid specification of min/max values for %s: %s/%s" %
1042 b342c9dd Bernardo Dal Seno
             (name, min_v, max_v))
1043 b342c9dd Bernardo Dal Seno
      raise errors.ConfigurationError(err)
1044 b342c9dd Bernardo Dal Seno
    elif check_std:
1045 da5f09ef Bernardo Dal Seno
      std_v = stdspec.get(name, min_v)
1046 b342c9dd Bernardo Dal Seno
      return std_v >= min_v and std_v <= max_v
1047 8b057218 Renรฉ Nussbaumer
    else:
1048 b342c9dd Bernardo Dal Seno
      return True
1049 918eb80b Agata Murawska
1050 2cc673a3 Iustin Pop
  @classmethod
1051 2cc673a3 Iustin Pop
  def CheckDiskTemplates(cls, disk_templates):
1052 2cc673a3 Iustin Pop
    """Checks the disk templates for validity.
1053 2cc673a3 Iustin Pop

1054 2cc673a3 Iustin Pop
    """
1055 ba5c6c6b Bernardo Dal Seno
    if not disk_templates:
1056 ba5c6c6b Bernardo Dal Seno
      raise errors.ConfigurationError("Instance policy must contain" +
1057 ba5c6c6b Bernardo Dal Seno
                                      " at least one disk template")
1058 2cc673a3 Iustin Pop
    wrong = frozenset(disk_templates).difference(constants.DISK_TEMPLATES)
1059 2cc673a3 Iustin Pop
    if wrong:
1060 2cc673a3 Iustin Pop
      raise errors.ConfigurationError("Invalid disk template(s) %s" %
1061 2cc673a3 Iustin Pop
                                      utils.CommaJoin(wrong))
1062 2cc673a3 Iustin Pop
1063 ff6c5e55 Iustin Pop
  @classmethod
1064 ff6c5e55 Iustin Pop
  def CheckParameter(cls, key, value):
1065 ff6c5e55 Iustin Pop
    """Checks a parameter.
1066 ff6c5e55 Iustin Pop

1067 ff6c5e55 Iustin Pop
    Currently we expect all parameters to be float values.
1068 ff6c5e55 Iustin Pop

1069 ff6c5e55 Iustin Pop
    """
1070 ff6c5e55 Iustin Pop
    try:
1071 ff6c5e55 Iustin Pop
      float(value)
1072 ff6c5e55 Iustin Pop
    except (TypeError, ValueError), err:
1073 ff6c5e55 Iustin Pop
      raise errors.ConfigurationError("Invalid value for key" " '%s':"
1074 ff6c5e55 Iustin Pop
                                      " '%s', error: %s" % (key, value, err))
1075 ff6c5e55 Iustin Pop
1076 918eb80b Agata Murawska
1077 433d2933 Jose A. Lopes
def GetOSImage(osparams):
1078 433d2933 Jose A. Lopes
  """Gets the OS image value from the OS parameters.
1079 433d2933 Jose A. Lopes

1080 433d2933 Jose A. Lopes
  @type osparams: L{dict} or NoneType
1081 433d2933 Jose A. Lopes
  @param osparams: OS parameters or None
1082 433d2933 Jose A. Lopes

1083 433d2933 Jose A. Lopes
  @rtype: string or NoneType
1084 433d2933 Jose A. Lopes
  @return:
1085 433d2933 Jose A. Lopes
    value of OS image contained in OS parameters, or None if the OS
1086 433d2933 Jose A. Lopes
    parameters are None or the OS parameters do not contain an OS
1087 433d2933 Jose A. Lopes
    image
1088 433d2933 Jose A. Lopes

1089 433d2933 Jose A. Lopes
  """
1090 433d2933 Jose A. Lopes
  if osparams is None:
1091 433d2933 Jose A. Lopes
    return None
1092 433d2933 Jose A. Lopes
  else:
1093 433d2933 Jose A. Lopes
    return osparams.get("os-image", None)
1094 433d2933 Jose A. Lopes
1095 433d2933 Jose A. Lopes
1096 433d2933 Jose A. Lopes
def PutOSImage(osparams, os_image):
1097 433d2933 Jose A. Lopes
  """Update OS image value in the OS parameters
1098 433d2933 Jose A. Lopes

1099 433d2933 Jose A. Lopes
  @type osparams: L{dict}
1100 433d2933 Jose A. Lopes
  @param osparams: OS parameters
1101 433d2933 Jose A. Lopes

1102 433d2933 Jose A. Lopes
  @type os_image: string
1103 433d2933 Jose A. Lopes
  @param os_image: OS image
1104 433d2933 Jose A. Lopes

1105 433d2933 Jose A. Lopes
  @rtype: NoneType
1106 433d2933 Jose A. Lopes
  @return: None
1107 433d2933 Jose A. Lopes

1108 433d2933 Jose A. Lopes
  """
1109 433d2933 Jose A. Lopes
  osparams["os-image"] = os_image
1110 433d2933 Jose A. Lopes
1111 433d2933 Jose A. Lopes
1112 ec29fe40 Iustin Pop
class Instance(TaggableObject):
1113 a8083063 Iustin Pop
  """Config object representing an instance."""
1114 154b9580 Balazs Lecz
  __slots__ = [
1115 a8083063 Iustin Pop
    "name",
1116 a8083063 Iustin Pop
    "primary_node",
1117 a8083063 Iustin Pop
    "os",
1118 e69d05fd Iustin Pop
    "hypervisor",
1119 5bf7b5cf Iustin Pop
    "hvparams",
1120 5bf7b5cf Iustin Pop
    "beparams",
1121 1bdcbbab Iustin Pop
    "osparams",
1122 a5efec93 Santi Raffa
    "osparams_private",
1123 9ca8a7c5 Agata Murawska
    "admin_state",
1124 a8083063 Iustin Pop
    "nics",
1125 a8083063 Iustin Pop
    "disks",
1126 a8083063 Iustin Pop
    "disk_template",
1127 1d4a4b26 Thomas Thrainer
    "disks_active",
1128 58acb49d Alexander Schreiber
    "network_port",
1129 be1fa613 Iustin Pop
    "serial_no",
1130 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
1131 a8083063 Iustin Pop
1132 a8083063 Iustin Pop
  def _ComputeSecondaryNodes(self):
1133 a8083063 Iustin Pop
    """Compute the list of secondary nodes.
1134 a8083063 Iustin Pop

1135 cfcc5c6d Iustin Pop
    This is a simple wrapper over _ComputeAllNodes.
1136 cfcc5c6d Iustin Pop

1137 cfcc5c6d Iustin Pop
    """
1138 cfcc5c6d Iustin Pop
    all_nodes = set(self._ComputeAllNodes())
1139 cfcc5c6d Iustin Pop
    all_nodes.discard(self.primary_node)
1140 cfcc5c6d Iustin Pop
    return tuple(all_nodes)
1141 cfcc5c6d Iustin Pop
1142 cfcc5c6d Iustin Pop
  secondary_nodes = property(_ComputeSecondaryNodes, None, None,
1143 05325a35 Bernardo Dal Seno
                             "List of names of secondary nodes")
1144 cfcc5c6d Iustin Pop
1145 cfcc5c6d Iustin Pop
  def _ComputeAllNodes(self):
1146 cfcc5c6d Iustin Pop
    """Compute the list of all nodes.
1147 cfcc5c6d Iustin Pop

1148 a8083063 Iustin Pop
    Since the data is already there (in the drbd disks), keeping it as
1149 a8083063 Iustin Pop
    a separate normal attribute is redundant and if not properly
1150 a8083063 Iustin Pop
    synchronised can cause problems. Thus it's better to compute it
1151 a8083063 Iustin Pop
    dynamically.
1152 a8083063 Iustin Pop

1153 a8083063 Iustin Pop
    """
1154 cfcc5c6d Iustin Pop
    def _Helper(nodes, device):
1155 cfcc5c6d Iustin Pop
      """Recursively computes nodes given a top device."""
1156 66a37e7a Helga Velroyen
      if device.dev_type in constants.DTS_DRBD:
1157 cfcc5c6d Iustin Pop
        nodea, nodeb = device.logical_id[:2]
1158 cfcc5c6d Iustin Pop
        nodes.add(nodea)
1159 cfcc5c6d Iustin Pop
        nodes.add(nodeb)
1160 a8083063 Iustin Pop
      if device.children:
1161 a8083063 Iustin Pop
        for child in device.children:
1162 cfcc5c6d Iustin Pop
          _Helper(nodes, child)
1163 a8083063 Iustin Pop
1164 cfcc5c6d Iustin Pop
    all_nodes = set()
1165 a8083063 Iustin Pop
    for device in self.disks:
1166 cfcc5c6d Iustin Pop
      _Helper(all_nodes, device)
1167 f2a3c4f0 Petr Pudlak
    # ensure that the primary node is always the first
1168 f2a3c4f0 Petr Pudlak
    all_nodes.discard(self.primary_node)
1169 f2a3c4f0 Petr Pudlak
    return (self.primary_node, ) + tuple(all_nodes)
1170 a8083063 Iustin Pop
1171 cfcc5c6d Iustin Pop
  all_nodes = property(_ComputeAllNodes, None, None,
1172 05325a35 Bernardo Dal Seno
                       "List of names of all the nodes of the instance")
1173 a8083063 Iustin Pop
1174 843094ad Thomas Thrainer
  def MapLVsByNode(self, lvmap=None, devs=None, node_uuid=None):
1175 a8083063 Iustin Pop
    """Provide a mapping of nodes to LVs this instance owns.
1176 a8083063 Iustin Pop

1177 c41eea6e Iustin Pop
    This function figures out what logical volumes should belong on
1178 c41eea6e Iustin Pop
    which nodes, recursing through a device tree.
1179 a8083063 Iustin Pop

1180 843094ad Thomas Thrainer
    @type lvmap: dict
1181 c41eea6e Iustin Pop
    @param lvmap: optional dictionary to receive the
1182 c41eea6e Iustin Pop
        'node' : ['lv', ...] data.
1183 843094ad Thomas Thrainer
    @type devs: list of L{Disk}
1184 843094ad Thomas Thrainer
    @param devs: disks to get the LV name for. If None, all disk of this
1185 843094ad Thomas Thrainer
        instance are used.
1186 843094ad Thomas Thrainer
    @type node_uuid: string
1187 843094ad Thomas Thrainer
    @param node_uuid: UUID of the node to get the LV names for. If None, the
1188 843094ad Thomas Thrainer
        primary node of this instance is used.
1189 84d7e26b Dmitry Chernyak
    @return: None if lvmap arg is given, otherwise, a dictionary of
1190 1c3231aa Thomas Thrainer
        the form { 'node_uuid' : ['volume1', 'volume2', ...], ... };
1191 84d7e26b Dmitry Chernyak
        volumeN is of the form "vg_name/lv_name", compatible with
1192 84d7e26b Dmitry Chernyak
        GetVolumeList()
1193 a8083063 Iustin Pop

1194 a8083063 Iustin Pop
    """
1195 843094ad Thomas Thrainer
    if node_uuid is None:
1196 843094ad Thomas Thrainer
      node_uuid = self.primary_node
1197 a8083063 Iustin Pop
1198 a8083063 Iustin Pop
    if lvmap is None:
1199 e687ec01 Michael Hanselmann
      lvmap = {
1200 843094ad Thomas Thrainer
        node_uuid: [],
1201 e687ec01 Michael Hanselmann
        }
1202 a8083063 Iustin Pop
      ret = lvmap
1203 a8083063 Iustin Pop
    else:
1204 843094ad Thomas Thrainer
      if not node_uuid in lvmap:
1205 843094ad Thomas Thrainer
        lvmap[node_uuid] = []
1206 a8083063 Iustin Pop
      ret = None
1207 a8083063 Iustin Pop
1208 a8083063 Iustin Pop
    if not devs:
1209 a8083063 Iustin Pop
      devs = self.disks
1210 a8083063 Iustin Pop
1211 a8083063 Iustin Pop
    for dev in devs:
1212 cd3b4ff4 Helga Velroyen
      if dev.dev_type == constants.DT_PLAIN:
1213 843094ad Thomas Thrainer
        lvmap[node_uuid].append(dev.logical_id[0] + "/" + dev.logical_id[1])
1214 a8083063 Iustin Pop
1215 66a37e7a Helga Velroyen
      elif dev.dev_type in constants.DTS_DRBD:
1216 a8083063 Iustin Pop
        if dev.children:
1217 a8083063 Iustin Pop
          self.MapLVsByNode(lvmap, dev.children, dev.logical_id[0])
1218 a8083063 Iustin Pop
          self.MapLVsByNode(lvmap, dev.children, dev.logical_id[1])
1219 a8083063 Iustin Pop
1220 a8083063 Iustin Pop
      elif dev.children:
1221 843094ad Thomas Thrainer
        self.MapLVsByNode(lvmap, dev.children, node_uuid)
1222 a8083063 Iustin Pop
1223 a8083063 Iustin Pop
    return ret
1224 a8083063 Iustin Pop
1225 ad24e046 Iustin Pop
  def FindDisk(self, idx):
1226 ad24e046 Iustin Pop
    """Find a disk given having a specified index.
1227 644eeef9 Iustin Pop

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

1230 ad24e046 Iustin Pop
    @type idx: int
1231 ad24e046 Iustin Pop
    @param idx: the disk index
1232 ad24e046 Iustin Pop
    @rtype: L{Disk}
1233 ad24e046 Iustin Pop
    @return: the corresponding disk
1234 ad24e046 Iustin Pop
    @raise errors.OpPrereqError: when the given index is not valid
1235 644eeef9 Iustin Pop

1236 ad24e046 Iustin Pop
    """
1237 ad24e046 Iustin Pop
    try:
1238 ad24e046 Iustin Pop
      idx = int(idx)
1239 ad24e046 Iustin Pop
      return self.disks[idx]
1240 691744c4 Iustin Pop
    except (TypeError, ValueError), err:
1241 debac808 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index: '%s'" % str(err),
1242 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
1243 ad24e046 Iustin Pop
    except IndexError:
1244 ad24e046 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index: %d (instace has disks"
1245 daa55b04 Michael Hanselmann
                                 " 0 to %d" % (idx, len(self.disks) - 1),
1246 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
1247 644eeef9 Iustin Pop
1248 a5efec93 Santi Raffa
  def ToDict(self, _with_private=False):
1249 ff9c047c Iustin Pop
    """Instance-specific conversion to standard python types.
1250 ff9c047c Iustin Pop

1251 ff9c047c Iustin Pop
    This replaces the children lists of objects with lists of standard
1252 ff9c047c Iustin Pop
    python types.
1253 ff9c047c Iustin Pop

1254 ff9c047c Iustin Pop
    """
1255 a5efec93 Santi Raffa
    bo = super(Instance, self).ToDict(_with_private=_with_private)
1256 a5efec93 Santi Raffa
1257 a5efec93 Santi Raffa
    if _with_private:
1258 a5efec93 Santi Raffa
      bo["osparams_private"] = self.osparams_private.Unprivate()
1259 ff9c047c Iustin Pop
1260 ff9c047c Iustin Pop
    for attr in "nics", "disks":
1261 ff9c047c Iustin Pop
      alist = bo.get(attr, None)
1262 ff9c047c Iustin Pop
      if alist:
1263 fe502d25 Iustin Pop
        nlist = outils.ContainerToDicts(alist)
1264 ff9c047c Iustin Pop
      else:
1265 ff9c047c Iustin Pop
        nlist = []
1266 ff9c047c Iustin Pop
      bo[attr] = nlist
1267 ff9c047c Iustin Pop
    return bo
1268 ff9c047c Iustin Pop
1269 ff9c047c Iustin Pop
  @classmethod
1270 ff9c047c Iustin Pop
  def FromDict(cls, val):
1271 ff9c047c Iustin Pop
    """Custom function for instances.
1272 ff9c047c Iustin Pop

1273 ff9c047c Iustin Pop
    """
1274 9ca8a7c5 Agata Murawska
    if "admin_state" not in val:
1275 9ca8a7c5 Agata Murawska
      if val.get("admin_up", False):
1276 9ca8a7c5 Agata Murawska
        val["admin_state"] = constants.ADMINST_UP
1277 9ca8a7c5 Agata Murawska
      else:
1278 9ca8a7c5 Agata Murawska
        val["admin_state"] = constants.ADMINST_DOWN
1279 9ca8a7c5 Agata Murawska
    if "admin_up" in val:
1280 9ca8a7c5 Agata Murawska
      del val["admin_up"]
1281 ff9c047c Iustin Pop
    obj = super(Instance, cls).FromDict(val)
1282 fe502d25 Iustin Pop
    obj.nics = outils.ContainerFromDicts(obj.nics, list, NIC)
1283 fe502d25 Iustin Pop
    obj.disks = outils.ContainerFromDicts(obj.disks, list, Disk)
1284 ff9c047c Iustin Pop
    return obj
1285 ff9c047c Iustin Pop
1286 90d726a8 Iustin Pop
  def UpgradeConfig(self):
1287 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
1288 90d726a8 Iustin Pop

1289 90d726a8 Iustin Pop
    """
1290 90d726a8 Iustin Pop
    for nic in self.nics:
1291 90d726a8 Iustin Pop
      nic.UpgradeConfig()
1292 90d726a8 Iustin Pop
    for disk in self.disks:
1293 90d726a8 Iustin Pop
      disk.UpgradeConfig()
1294 7736a5f2 Iustin Pop
    if self.hvparams:
1295 7736a5f2 Iustin Pop
      for key in constants.HVC_GLOBALS:
1296 7736a5f2 Iustin Pop
        try:
1297 7736a5f2 Iustin Pop
          del self.hvparams[key]
1298 7736a5f2 Iustin Pop
        except KeyError:
1299 7736a5f2 Iustin Pop
          pass
1300 1bdcbbab Iustin Pop
    if self.osparams is None:
1301 1bdcbbab Iustin Pop
      self.osparams = {}
1302 a5efec93 Santi Raffa
    if self.osparams_private is None:
1303 a5efec93 Santi Raffa
      self.osparams_private = serializer.PrivateDict()
1304 8c72ab2b Guido Trotter
    UpgradeBeParams(self.beparams)
1305 a8e07057 Thomas Thrainer
    if self.disks_active is None:
1306 a8e07057 Thomas Thrainer
      self.disks_active = self.admin_state == constants.ADMINST_UP
1307 90d726a8 Iustin Pop
1308 a8083063 Iustin Pop
1309 a8083063 Iustin Pop
class OS(ConfigObject):
1310 b41b3516 Iustin Pop
  """Config object representing an operating system.
1311 b41b3516 Iustin Pop

1312 b41b3516 Iustin Pop
  @type supported_parameters: list
1313 b41b3516 Iustin Pop
  @ivar supported_parameters: a list of tuples, name and description,
1314 b41b3516 Iustin Pop
      containing the supported parameters by this OS
1315 b41b3516 Iustin Pop

1316 870dc44c Iustin Pop
  @type VARIANT_DELIM: string
1317 870dc44c Iustin Pop
  @cvar VARIANT_DELIM: the variant delimiter
1318 870dc44c Iustin Pop

1319 b41b3516 Iustin Pop
  """
1320 a8083063 Iustin Pop
  __slots__ = [
1321 a8083063 Iustin Pop
    "name",
1322 a8083063 Iustin Pop
    "path",
1323 082a7f91 Guido Trotter
    "api_versions",
1324 a8083063 Iustin Pop
    "create_script",
1325 a8083063 Iustin Pop
    "export_script",
1326 386b57af Iustin Pop
    "import_script",
1327 386b57af Iustin Pop
    "rename_script",
1328 b41b3516 Iustin Pop
    "verify_script",
1329 6d79896b Guido Trotter
    "supported_variants",
1330 b41b3516 Iustin Pop
    "supported_parameters",
1331 a8083063 Iustin Pop
    ]
1332 a8083063 Iustin Pop
1333 870dc44c Iustin Pop
  VARIANT_DELIM = "+"
1334 870dc44c Iustin Pop
1335 870dc44c Iustin Pop
  @classmethod
1336 870dc44c Iustin Pop
  def SplitNameVariant(cls, name):
1337 870dc44c Iustin Pop
    """Splits the name into the proper name and variant.
1338 870dc44c Iustin Pop

1339 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
1340 870dc44c Iustin Pop
    @rtype: list
1341 870dc44c Iustin Pop
    @return: a list of two elements; if the original name didn't
1342 870dc44c Iustin Pop
        contain a variant, it's returned as an empty string
1343 870dc44c Iustin Pop

1344 870dc44c Iustin Pop
    """
1345 870dc44c Iustin Pop
    nv = name.split(cls.VARIANT_DELIM, 1)
1346 870dc44c Iustin Pop
    if len(nv) == 1:
1347 870dc44c Iustin Pop
      nv.append("")
1348 870dc44c Iustin Pop
    return nv
1349 870dc44c Iustin Pop
1350 870dc44c Iustin Pop
  @classmethod
1351 870dc44c Iustin Pop
  def GetName(cls, name):
1352 870dc44c Iustin Pop
    """Returns the proper name of the os (without the variant).
1353 870dc44c Iustin Pop

1354 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
1355 870dc44c Iustin Pop

1356 870dc44c Iustin Pop
    """
1357 870dc44c Iustin Pop
    return cls.SplitNameVariant(name)[0]
1358 870dc44c Iustin Pop
1359 870dc44c Iustin Pop
  @classmethod
1360 870dc44c Iustin Pop
  def GetVariant(cls, name):
1361 870dc44c Iustin Pop
    """Returns the variant the os (without the base name).
1362 870dc44c Iustin Pop

1363 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
1364 870dc44c Iustin Pop

1365 870dc44c Iustin Pop
    """
1366 870dc44c Iustin Pop
    return cls.SplitNameVariant(name)[1]
1367 870dc44c Iustin Pop
1368 7c0d6283 Michael Hanselmann
1369 376631d1 Constantinos Venetsanopoulos
class ExtStorage(ConfigObject):
1370 376631d1 Constantinos Venetsanopoulos
  """Config object representing an External Storage Provider.
1371 376631d1 Constantinos Venetsanopoulos

1372 376631d1 Constantinos Venetsanopoulos
  """
1373 376631d1 Constantinos Venetsanopoulos
  __slots__ = [
1374 376631d1 Constantinos Venetsanopoulos
    "name",
1375 376631d1 Constantinos Venetsanopoulos
    "path",
1376 376631d1 Constantinos Venetsanopoulos
    "create_script",
1377 376631d1 Constantinos Venetsanopoulos
    "remove_script",
1378 376631d1 Constantinos Venetsanopoulos
    "grow_script",
1379 376631d1 Constantinos Venetsanopoulos
    "attach_script",
1380 376631d1 Constantinos Venetsanopoulos
    "detach_script",
1381 376631d1 Constantinos Venetsanopoulos
    "setinfo_script",
1382 938adc87 Constantinos Venetsanopoulos
    "verify_script",
1383 938adc87 Constantinos Venetsanopoulos
    "supported_parameters",
1384 376631d1 Constantinos Venetsanopoulos
    ]
1385 376631d1 Constantinos Venetsanopoulos
1386 376631d1 Constantinos Venetsanopoulos
1387 5f06ce5e Michael Hanselmann
class NodeHvState(ConfigObject):
1388 5f06ce5e Michael Hanselmann
  """Hypvervisor state on a node.
1389 5f06ce5e Michael Hanselmann

1390 5f06ce5e Michael Hanselmann
  @ivar mem_total: Total amount of memory
1391 5f06ce5e Michael Hanselmann
  @ivar mem_node: Memory used by, or reserved for, the node itself (not always
1392 5f06ce5e Michael Hanselmann
    available)
1393 5f06ce5e Michael Hanselmann
  @ivar mem_hv: Memory used by hypervisor or lost due to instance allocation
1394 5f06ce5e Michael Hanselmann
    rounding
1395 5f06ce5e Michael Hanselmann
  @ivar mem_inst: Memory used by instances living on node
1396 5f06ce5e Michael Hanselmann
  @ivar cpu_total: Total node CPU core count
1397 5f06ce5e Michael Hanselmann
  @ivar cpu_node: Number of CPU cores reserved for the node itself
1398 5f06ce5e Michael Hanselmann

1399 5f06ce5e Michael Hanselmann
  """
1400 5f06ce5e Michael Hanselmann
  __slots__ = [
1401 5f06ce5e Michael Hanselmann
    "mem_total",
1402 5f06ce5e Michael Hanselmann
    "mem_node",
1403 5f06ce5e Michael Hanselmann
    "mem_hv",
1404 5f06ce5e Michael Hanselmann
    "mem_inst",
1405 5f06ce5e Michael Hanselmann
    "cpu_total",
1406 5f06ce5e Michael Hanselmann
    "cpu_node",
1407 5f06ce5e Michael Hanselmann
    ] + _TIMESTAMPS
1408 5f06ce5e Michael Hanselmann
1409 5f06ce5e Michael Hanselmann
1410 5f06ce5e Michael Hanselmann
class NodeDiskState(ConfigObject):
1411 5f06ce5e Michael Hanselmann
  """Disk state on a node.
1412 5f06ce5e Michael Hanselmann

1413 5f06ce5e Michael Hanselmann
  """
1414 5f06ce5e Michael Hanselmann
  __slots__ = [
1415 5f06ce5e Michael Hanselmann
    "total",
1416 5f06ce5e Michael Hanselmann
    "reserved",
1417 5f06ce5e Michael Hanselmann
    "overhead",
1418 5f06ce5e Michael Hanselmann
    ] + _TIMESTAMPS
1419 5f06ce5e Michael Hanselmann
1420 5f06ce5e Michael Hanselmann
1421 ec29fe40 Iustin Pop
class Node(TaggableObject):
1422 634d30f4 Michael Hanselmann
  """Config object representing a node.
1423 634d30f4 Michael Hanselmann

1424 634d30f4 Michael Hanselmann
  @ivar hv_state: Hypervisor state (e.g. number of CPUs)
1425 634d30f4 Michael Hanselmann
  @ivar hv_state_static: Hypervisor state overriden by user
1426 634d30f4 Michael Hanselmann
  @ivar disk_state: Disk state (e.g. free space)
1427 634d30f4 Michael Hanselmann
  @ivar disk_state_static: Disk state overriden by user
1428 634d30f4 Michael Hanselmann

1429 634d30f4 Michael Hanselmann
  """
1430 154b9580 Balazs Lecz
  __slots__ = [
1431 ec29fe40 Iustin Pop
    "name",
1432 ec29fe40 Iustin Pop
    "primary_ip",
1433 ec29fe40 Iustin Pop
    "secondary_ip",
1434 be1fa613 Iustin Pop
    "serial_no",
1435 8b8b8b81 Iustin Pop
    "master_candidate",
1436 fc0fe88c Iustin Pop
    "offline",
1437 af64c0ea Iustin Pop
    "drained",
1438 f936c153 Iustin Pop
    "group",
1439 490acd18 Iustin Pop
    "master_capable",
1440 490acd18 Iustin Pop
    "vm_capable",
1441 095e71aa Renรฉ Nussbaumer
    "ndparams",
1442 25124d4a Renรฉ Nussbaumer
    "powered",
1443 5b49ed09 Renรฉ Nussbaumer
    "hv_state",
1444 634d30f4 Michael Hanselmann
    "hv_state_static",
1445 5b49ed09 Renรฉ Nussbaumer
    "disk_state",
1446 634d30f4 Michael Hanselmann
    "disk_state_static",
1447 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
1448 a8083063 Iustin Pop
1449 490acd18 Iustin Pop
  def UpgradeConfig(self):
1450 490acd18 Iustin Pop
    """Fill defaults for missing configuration values.
1451 490acd18 Iustin Pop

1452 490acd18 Iustin Pop
    """
1453 b459a848 Andrea Spadaccini
    # pylint: disable=E0203
1454 490acd18 Iustin Pop
    # because these are "defined" via slots, not manually
1455 490acd18 Iustin Pop
    if self.master_capable is None:
1456 490acd18 Iustin Pop
      self.master_capable = True
1457 490acd18 Iustin Pop
1458 490acd18 Iustin Pop
    if self.vm_capable is None:
1459 490acd18 Iustin Pop
      self.vm_capable = True
1460 490acd18 Iustin Pop
1461 095e71aa Renรฉ Nussbaumer
    if self.ndparams is None:
1462 095e71aa Renรฉ Nussbaumer
      self.ndparams = {}
1463 250a9404 Bernardo Dal Seno
    # And remove any global parameter
1464 250a9404 Bernardo Dal Seno
    for key in constants.NDC_GLOBALS:
1465 250a9404 Bernardo Dal Seno
      if key in self.ndparams:
1466 250a9404 Bernardo Dal Seno
        logging.warning("Ignoring %s node parameter for node %s",
1467 250a9404 Bernardo Dal Seno
                        key, self.name)
1468 250a9404 Bernardo Dal Seno
        del self.ndparams[key]
1469 095e71aa Renรฉ Nussbaumer
1470 25124d4a Renรฉ Nussbaumer
    if self.powered is None:
1471 25124d4a Renรฉ Nussbaumer
      self.powered = True
1472 25124d4a Renรฉ Nussbaumer
1473 a5efec93 Santi Raffa
  def ToDict(self, _with_private=False):
1474 5f06ce5e Michael Hanselmann
    """Custom function for serializing.
1475 5f06ce5e Michael Hanselmann

1476 5f06ce5e Michael Hanselmann
    """
1477 a5efec93 Santi Raffa
    data = super(Node, self).ToDict(_with_private=_with_private)
1478 5f06ce5e Michael Hanselmann
1479 5f06ce5e Michael Hanselmann
    hv_state = data.get("hv_state", None)
1480 5f06ce5e Michael Hanselmann
    if hv_state is not None:
1481 fe502d25 Iustin Pop
      data["hv_state"] = outils.ContainerToDicts(hv_state)
1482 5f06ce5e Michael Hanselmann
1483 5f06ce5e Michael Hanselmann
    disk_state = data.get("disk_state", None)
1484 5f06ce5e Michael Hanselmann
    if disk_state is not None:
1485 5f06ce5e Michael Hanselmann
      data["disk_state"] = \
1486 fe502d25 Iustin Pop
        dict((key, outils.ContainerToDicts(value))
1487 5f06ce5e Michael Hanselmann
             for (key, value) in disk_state.items())
1488 5f06ce5e Michael Hanselmann
1489 5f06ce5e Michael Hanselmann
    return data
1490 5f06ce5e Michael Hanselmann
1491 5f06ce5e Michael Hanselmann
  @classmethod
1492 5f06ce5e Michael Hanselmann
  def FromDict(cls, val):
1493 5f06ce5e Michael Hanselmann
    """Custom function for deserializing.
1494 5f06ce5e Michael Hanselmann

1495 5f06ce5e Michael Hanselmann
    """
1496 5f06ce5e Michael Hanselmann
    obj = super(Node, cls).FromDict(val)
1497 5f06ce5e Michael Hanselmann
1498 5f06ce5e Michael Hanselmann
    if obj.hv_state is not None:
1499 473ab806 Michael Hanselmann
      obj.hv_state = \
1500 fe502d25 Iustin Pop
        outils.ContainerFromDicts(obj.hv_state, dict, NodeHvState)
1501 5f06ce5e Michael Hanselmann
1502 5f06ce5e Michael Hanselmann
    if obj.disk_state is not None:
1503 5f06ce5e Michael Hanselmann
      obj.disk_state = \
1504 fe502d25 Iustin Pop
        dict((key, outils.ContainerFromDicts(value, dict, NodeDiskState))
1505 5f06ce5e Michael Hanselmann
             for (key, value) in obj.disk_state.items())
1506 5f06ce5e Michael Hanselmann
1507 5f06ce5e Michael Hanselmann
    return obj
1508 5f06ce5e Michael Hanselmann
1509 a8083063 Iustin Pop
1510 1ffd2673 Michael Hanselmann
class NodeGroup(TaggableObject):
1511 24a3707f Guido Trotter
  """Config object representing a node group."""
1512 24a3707f Guido Trotter
  __slots__ = [
1513 24a3707f Guido Trotter
    "name",
1514 24a3707f Guido Trotter
    "members",
1515 095e71aa Renรฉ Nussbaumer
    "ndparams",
1516 bc5d0215 Andrea Spadaccini
    "diskparams",
1517 81e3ab4f Agata Murawska
    "ipolicy",
1518 e11a1b77 Adeodato Simo
    "serial_no",
1519 a8282327 Renรฉ Nussbaumer
    "hv_state_static",
1520 a8282327 Renรฉ Nussbaumer
    "disk_state_static",
1521 90e99856 Adeodato Simo
    "alloc_policy",
1522 eaa4c57c Dimitris Aragiorgis
    "networks",
1523 24a3707f Guido Trotter
    ] + _TIMESTAMPS + _UUID
1524 24a3707f Guido Trotter
1525 a5efec93 Santi Raffa
  def ToDict(self, _with_private=False):
1526 24a3707f Guido Trotter
    """Custom function for nodegroup.
1527 24a3707f Guido Trotter

1528 c60abd62 Guido Trotter
    This discards the members object, which gets recalculated and is only kept
1529 c60abd62 Guido Trotter
    in memory.
1530 24a3707f Guido Trotter

1531 24a3707f Guido Trotter
    """
1532 a5efec93 Santi Raffa
    mydict = super(NodeGroup, self).ToDict(_with_private=_with_private)
1533 24a3707f Guido Trotter
    del mydict["members"]
1534 24a3707f Guido Trotter
    return mydict
1535 24a3707f Guido Trotter
1536 24a3707f Guido Trotter
  @classmethod
1537 24a3707f Guido Trotter
  def FromDict(cls, val):
1538 24a3707f Guido Trotter
    """Custom function for nodegroup.
1539 24a3707f Guido Trotter

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

1542 24a3707f Guido Trotter
    """
1543 24a3707f Guido Trotter
    obj = super(NodeGroup, cls).FromDict(val)
1544 24a3707f Guido Trotter
    obj.members = []
1545 24a3707f Guido Trotter
    return obj
1546 24a3707f Guido Trotter
1547 095e71aa Renรฉ Nussbaumer
  def UpgradeConfig(self):
1548 095e71aa Renรฉ Nussbaumer
    """Fill defaults for missing configuration values.
1549 095e71aa Renรฉ Nussbaumer

1550 095e71aa Renรฉ Nussbaumer
    """
1551 095e71aa Renรฉ Nussbaumer
    if self.ndparams is None:
1552 095e71aa Renรฉ Nussbaumer
      self.ndparams = {}
1553 095e71aa Renรฉ Nussbaumer
1554 e11a1b77 Adeodato Simo
    if self.serial_no is None:
1555 e11a1b77 Adeodato Simo
      self.serial_no = 1
1556 e11a1b77 Adeodato Simo
1557 90e99856 Adeodato Simo
    if self.alloc_policy is None:
1558 90e99856 Adeodato Simo
      self.alloc_policy = constants.ALLOC_POLICY_PREFERRED
1559 90e99856 Adeodato Simo
1560 4b97458c Iustin Pop
    # We only update mtime, and not ctime, since we would not be able
1561 4b97458c Iustin Pop
    # to provide a correct value for creation time.
1562 e11a1b77 Adeodato Simo
    if self.mtime is None:
1563 e11a1b77 Adeodato Simo
      self.mtime = time.time()
1564 e11a1b77 Adeodato Simo
1565 7228ca91 Renรฉ Nussbaumer
    if self.diskparams is None:
1566 7228ca91 Renรฉ Nussbaumer
      self.diskparams = {}
1567 81e3ab4f Agata Murawska
    if self.ipolicy is None:
1568 81e3ab4f Agata Murawska
      self.ipolicy = MakeEmptyIPolicy()
1569 bc5d0215 Andrea Spadaccini
1570 eaa4c57c Dimitris Aragiorgis
    if self.networks is None:
1571 eaa4c57c Dimitris Aragiorgis
      self.networks = {}
1572 eaa4c57c Dimitris Aragiorgis
1573 095e71aa Renรฉ Nussbaumer
  def FillND(self, node):
1574 ce523de1 Michael Hanselmann
    """Return filled out ndparams for L{objects.Node}
1575 095e71aa Renรฉ Nussbaumer

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

1580 095e71aa Renรฉ Nussbaumer
    """
1581 095e71aa Renรฉ Nussbaumer
    return self.SimpleFillND(node.ndparams)
1582 095e71aa Renรฉ Nussbaumer
1583 095e71aa Renรฉ Nussbaumer
  def SimpleFillND(self, ndparams):
1584 095e71aa Renรฉ Nussbaumer
    """Fill a given ndparams dict with defaults.
1585 095e71aa Renรฉ Nussbaumer

1586 095e71aa Renรฉ Nussbaumer
    @type ndparams: dict
1587 095e71aa Renรฉ Nussbaumer
    @param ndparams: the dict to fill
1588 095e71aa Renรฉ Nussbaumer
    @rtype: dict
1589 095e71aa Renรฉ Nussbaumer
    @return: a copy of the passed in ndparams with missing keys filled
1590 e6e88de6 Adeodato Simo
        from the node group defaults
1591 095e71aa Renรฉ Nussbaumer

1592 095e71aa Renรฉ Nussbaumer
    """
1593 095e71aa Renรฉ Nussbaumer
    return FillDict(self.ndparams, ndparams)
1594 095e71aa Renรฉ Nussbaumer
1595 24a3707f Guido Trotter
1596 ec29fe40 Iustin Pop
class Cluster(TaggableObject):
1597 a8083063 Iustin Pop
  """Config object representing the cluster."""
1598 154b9580 Balazs Lecz
  __slots__ = [
1599 a8083063 Iustin Pop
    "serial_no",
1600 a8083063 Iustin Pop
    "rsahostkeypub",
1601 a9542a4f Thomas Thrainer
    "dsahostkeypub",
1602 a8083063 Iustin Pop
    "highest_used_port",
1603 b2fddf63 Iustin Pop
    "tcpudp_port_pool",
1604 a8083063 Iustin Pop
    "mac_prefix",
1605 a8083063 Iustin Pop
    "volume_group_name",
1606 999b183c Iustin Pop
    "reserved_lvs",
1607 9e33896b Luca Bigliardi
    "drbd_usermode_helper",
1608 a8083063 Iustin Pop
    "default_bridge",
1609 02691904 Alexander Schreiber
    "default_hypervisor",
1610 f6bd6e98 Michael Hanselmann
    "master_node",
1611 f6bd6e98 Michael Hanselmann
    "master_ip",
1612 f6bd6e98 Michael Hanselmann
    "master_netdev",
1613 5a8648eb Andrea Spadaccini
    "master_netmask",
1614 33be7576 Andrea Spadaccini
    "use_external_mip_script",
1615 f6bd6e98 Michael Hanselmann
    "cluster_name",
1616 f6bd6e98 Michael Hanselmann
    "file_storage_dir",
1617 4b97f902 Apollon Oikonomopoulos
    "shared_file_storage_dir",
1618 d3e6fd0e Santi Raffa
    "gluster_storage_dir",
1619 e69d05fd Iustin Pop
    "enabled_hypervisors",
1620 5bf7b5cf Iustin Pop
    "hvparams",
1621 918eb80b Agata Murawska
    "ipolicy",
1622 17463d22 Renรฉ Nussbaumer
    "os_hvp",
1623 5bf7b5cf Iustin Pop
    "beparams",
1624 1bdcbbab Iustin Pop
    "osparams",
1625 a5efec93 Santi Raffa
    "osparams_private_cluster",
1626 c8fcde47 Guido Trotter
    "nicparams",
1627 095e71aa Renรฉ Nussbaumer
    "ndparams",
1628 bc5d0215 Andrea Spadaccini
    "diskparams",
1629 4b7735f9 Iustin Pop
    "candidate_pool_size",
1630 b86a6bcd Guido Trotter
    "modify_etc_hosts",
1631 b989b9d9 Ken Wehr
    "modify_ssh_setup",
1632 3953242f Iustin Pop
    "maintain_node_health",
1633 4437d889 Balazs Lecz
    "uid_pool",
1634 bf4af505 Apollon Oikonomopoulos
    "default_iallocator",
1635 0359e5d0 Spyros Trigazis
    "default_iallocator_params",
1636 87b2cd45 Iustin Pop
    "hidden_os",
1637 87b2cd45 Iustin Pop
    "blacklisted_os",
1638 2f20d07b Manuel Franceschini
    "primary_ip_family",
1639 3d914585 Renรฉ Nussbaumer
    "prealloc_wipe_disks",
1640 2da9f556 Renรฉ Nussbaumer
    "hv_state_static",
1641 2da9f556 Renรฉ Nussbaumer
    "disk_state_static",
1642 1b02d7ef Helga Velroyen
    "enabled_disk_templates",
1643 3bcf2140 Helga Velroyen
    "candidate_certs",
1644 cf048aea Klaus Aehlig
    "max_running_jobs",
1645 8a5d326f Jose A. Lopes
    "instance_communication_network",
1646 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
1647 a8083063 Iustin Pop
1648 b86a6bcd Guido Trotter
  def UpgradeConfig(self):
1649 b86a6bcd Guido Trotter
    """Fill defaults for missing configuration values.
1650 b86a6bcd Guido Trotter

1651 b86a6bcd Guido Trotter
    """
1652 b459a848 Andrea Spadaccini
    # pylint: disable=E0203
1653 fe267188 Iustin Pop
    # because these are "defined" via slots, not manually
1654 c1b42c18 Guido Trotter
    if self.hvparams is None:
1655 c1b42c18 Guido Trotter
      self.hvparams = constants.HVC_DEFAULTS
1656 c1b42c18 Guido Trotter
    else:
1657 6ee8fdd3 Michele Tartara
      for hypervisor in constants.HYPER_TYPES:
1658 6ee8fdd3 Michele Tartara
        try:
1659 6ee8fdd3 Michele Tartara
          existing_params = self.hvparams[hypervisor]
1660 6ee8fdd3 Michele Tartara
        except KeyError:
1661 6ee8fdd3 Michele Tartara
          existing_params = {}
1662 abe609b2 Guido Trotter
        self.hvparams[hypervisor] = FillDict(
1663 6ee8fdd3 Michele Tartara
            constants.HVC_DEFAULTS[hypervisor], existing_params)
1664 c1b42c18 Guido Trotter
1665 17463d22 Renรฉ Nussbaumer
    if self.os_hvp is None:
1666 17463d22 Renรฉ Nussbaumer
      self.os_hvp = {}
1667 17463d22 Renรฉ Nussbaumer
1668 1bdcbbab Iustin Pop
    if self.osparams is None:
1669 1bdcbbab Iustin Pop
      self.osparams = {}
1670 a5efec93 Santi Raffa
    # osparams_private_cluster added in 2.12
1671 a5efec93 Santi Raffa
    if self.osparams_private_cluster is None:
1672 a5efec93 Santi Raffa
      self.osparams_private_cluster = {}
1673 1bdcbbab Iustin Pop
1674 2a27dac3 Iustin Pop
    self.ndparams = UpgradeNDParams(self.ndparams)
1675 095e71aa Renรฉ Nussbaumer
1676 6e34b628 Guido Trotter
    self.beparams = UpgradeGroupedParams(self.beparams,
1677 6e34b628 Guido Trotter
                                         constants.BEC_DEFAULTS)
1678 8c72ab2b Guido Trotter
    for beparams_group in self.beparams:
1679 8c72ab2b Guido Trotter
      UpgradeBeParams(self.beparams[beparams_group])
1680 8c72ab2b Guido Trotter
1681 c8fcde47 Guido Trotter
    migrate_default_bridge = not self.nicparams
1682 c8fcde47 Guido Trotter
    self.nicparams = UpgradeGroupedParams(self.nicparams,
1683 c8fcde47 Guido Trotter
                                          constants.NICC_DEFAULTS)
1684 c8fcde47 Guido Trotter
    if migrate_default_bridge:
1685 c8fcde47 Guido Trotter
      self.nicparams[constants.PP_DEFAULT][constants.NIC_LINK] = \
1686 c8fcde47 Guido Trotter
        self.default_bridge
1687 c1b42c18 Guido Trotter
1688 b86a6bcd Guido Trotter
    if self.modify_etc_hosts is None:
1689 b86a6bcd Guido Trotter
      self.modify_etc_hosts = True
1690 b86a6bcd Guido Trotter
1691 b989b9d9 Ken Wehr
    if self.modify_ssh_setup is None:
1692 b989b9d9 Ken Wehr
      self.modify_ssh_setup = True
1693 b989b9d9 Ken Wehr
1694 73f1d185 Stephen Shirley
    # default_bridge is no longer used in 2.1. The slot is left there to
1695 90d118fd Guido Trotter
    # support auto-upgrading. It can be removed once we decide to deprecate
1696 90d118fd Guido Trotter
    # upgrading straight from 2.0.
1697 9b31ca85 Guido Trotter
    if self.default_bridge is not None:
1698 9b31ca85 Guido Trotter
      self.default_bridge = None
1699 9b31ca85 Guido Trotter
1700 90d118fd Guido Trotter
    # default_hypervisor is just the first enabled one in 2.1. This slot and
1701 90d118fd Guido Trotter
    # code can be removed once upgrading straight from 2.0 is deprecated.
1702 066f465d Guido Trotter
    if self.default_hypervisor is not None:
1703 016d04b3 Michael Hanselmann
      self.enabled_hypervisors = ([self.default_hypervisor] +
1704 5ae4945a Iustin Pop
                                  [hvname for hvname in self.enabled_hypervisors
1705 5ae4945a Iustin Pop
                                   if hvname != self.default_hypervisor])
1706 066f465d Guido Trotter
      self.default_hypervisor = None
1707 066f465d Guido Trotter
1708 3953242f Iustin Pop
    # maintain_node_health added after 2.1.1
1709 3953242f Iustin Pop
    if self.maintain_node_health is None:
1710 3953242f Iustin Pop
      self.maintain_node_health = False
1711 3953242f Iustin Pop
1712 4437d889 Balazs Lecz
    if self.uid_pool is None:
1713 4437d889 Balazs Lecz
      self.uid_pool = []
1714 4437d889 Balazs Lecz
1715 bf4af505 Apollon Oikonomopoulos
    if self.default_iallocator is None:
1716 bf4af505 Apollon Oikonomopoulos
      self.default_iallocator = ""
1717 bf4af505 Apollon Oikonomopoulos
1718 0359e5d0 Spyros Trigazis
    if self.default_iallocator_params is None:
1719 0359e5d0 Spyros Trigazis
      self.default_iallocator_params = {}
1720 0359e5d0 Spyros Trigazis
1721 999b183c Iustin Pop
    # reserved_lvs added before 2.2
1722 999b183c Iustin Pop
    if self.reserved_lvs is None:
1723 999b183c Iustin Pop
      self.reserved_lvs = []
1724 999b183c Iustin Pop
1725 546b1111 Iustin Pop
    # hidden and blacklisted operating systems added before 2.2.1
1726 87b2cd45 Iustin Pop
    if self.hidden_os is None:
1727 87b2cd45 Iustin Pop
      self.hidden_os = []
1728 546b1111 Iustin Pop
1729 87b2cd45 Iustin Pop
    if self.blacklisted_os is None:
1730 87b2cd45 Iustin Pop
      self.blacklisted_os = []
1731 546b1111 Iustin Pop
1732 f4c9af7a Guido Trotter
    # primary_ip_family added before 2.3
1733 f4c9af7a Guido Trotter
    if self.primary_ip_family is None:
1734 f4c9af7a Guido Trotter
      self.primary_ip_family = AF_INET
1735 f4c9af7a Guido Trotter
1736 0007f3ab Andrea Spadaccini
    if self.master_netmask is None:
1737 0007f3ab Andrea Spadaccini
      ipcls = netutils.IPAddress.GetClassFromIpFamily(self.primary_ip_family)
1738 0007f3ab Andrea Spadaccini
      self.master_netmask = ipcls.iplen
1739 0007f3ab Andrea Spadaccini
1740 3d914585 Renรฉ Nussbaumer
    if self.prealloc_wipe_disks is None:
1741 3d914585 Renรฉ Nussbaumer
      self.prealloc_wipe_disks = False
1742 3d914585 Renรฉ Nussbaumer
1743 e8f472d1 Iustin Pop
    # shared_file_storage_dir added before 2.5
1744 e8f472d1 Iustin Pop
    if self.shared_file_storage_dir is None:
1745 e8f472d1 Iustin Pop
      self.shared_file_storage_dir = ""
1746 e8f472d1 Iustin Pop
1747 d3e6fd0e Santi Raffa
    # gluster_storage_dir added in 2.11
1748 d3e6fd0e Santi Raffa
    if self.gluster_storage_dir is None:
1749 d3e6fd0e Santi Raffa
      self.gluster_storage_dir = ""
1750 d3e6fd0e Santi Raffa
1751 33be7576 Andrea Spadaccini
    if self.use_external_mip_script is None:
1752 33be7576 Andrea Spadaccini
      self.use_external_mip_script = False
1753 33be7576 Andrea Spadaccini
1754 99ccf8b9 Renรฉ Nussbaumer
    if self.diskparams:
1755 99ccf8b9 Renรฉ Nussbaumer
      self.diskparams = UpgradeDiskParams(self.diskparams)
1756 99ccf8b9 Renรฉ Nussbaumer
    else:
1757 99ccf8b9 Renรฉ Nussbaumer
      self.diskparams = constants.DISK_DT_DEFAULTS.copy()
1758 bc5d0215 Andrea Spadaccini
1759 918eb80b Agata Murawska
    # instance policy added before 2.6
1760 918eb80b Agata Murawska
    if self.ipolicy is None:
1761 2cc673a3 Iustin Pop
      self.ipolicy = FillIPolicy(constants.IPOLICY_DEFAULTS, {})
1762 38a6e2e1 Iustin Pop
    else:
1763 38a6e2e1 Iustin Pop
      # we can either make sure to upgrade the ipolicy always, or only
1764 38a6e2e1 Iustin Pop
      # do it in some corner cases (e.g. missing keys); note that this
1765 38a6e2e1 Iustin Pop
      # will break any removal of keys from the ipolicy dict
1766 4f7e5a1d Bernardo Dal Seno
      wrongkeys = frozenset(self.ipolicy.keys()) - constants.IPOLICY_ALL_KEYS
1767 4f7e5a1d Bernardo Dal Seno
      if wrongkeys:
1768 4f7e5a1d Bernardo Dal Seno
        # These keys would be silently removed by FillIPolicy()
1769 7fb852bd Michele Tartara
        msg = ("Cluster instance policy contains spurious keys: %s" %
1770 4f7e5a1d Bernardo Dal Seno
               utils.CommaJoin(wrongkeys))
1771 4f7e5a1d Bernardo Dal Seno
        raise errors.ConfigurationError(msg)
1772 38a6e2e1 Iustin Pop
      self.ipolicy = FillIPolicy(constants.IPOLICY_DEFAULTS, self.ipolicy)
1773 918eb80b Agata Murawska
1774 3bcf2140 Helga Velroyen
    if self.candidate_certs is None:
1775 3bcf2140 Helga Velroyen
      self.candidate_certs = {}
1776 3bcf2140 Helga Velroyen
1777 cf048aea Klaus Aehlig
    if self.max_running_jobs is None:
1778 cf048aea Klaus Aehlig
      self.max_running_jobs = constants.LUXID_MAXIMAL_RUNNING_JOBS_DEFAULT
1779 cf048aea Klaus Aehlig
1780 8a5d326f Jose A. Lopes
    if self.instance_communication_network is None:
1781 8a5d326f Jose A. Lopes
      self.instance_communication_network = ""
1782 8a5d326f Jose A. Lopes
1783 0fbedb7a Michael Hanselmann
  @property
1784 0fbedb7a Michael Hanselmann
  def primary_hypervisor(self):
1785 0fbedb7a Michael Hanselmann
    """The first hypervisor is the primary.
1786 0fbedb7a Michael Hanselmann

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

1789 0fbedb7a Michael Hanselmann
    """
1790 0fbedb7a Michael Hanselmann
    return self.enabled_hypervisors[0]
1791 0fbedb7a Michael Hanselmann
1792 a5efec93 Santi Raffa
  def ToDict(self, _with_private=False):
1793 319856a9 Michael Hanselmann
    """Custom function for cluster.
1794 319856a9 Michael Hanselmann

1795 319856a9 Michael Hanselmann
    """
1796 a5efec93 Santi Raffa
    mydict = super(Cluster, self).ToDict(_with_private=_with_private)
1797 a5efec93 Santi Raffa
1798 a5efec93 Santi Raffa
    # Explicitly save private parameters.
1799 a5efec93 Santi Raffa
    if _with_private:
1800 a5efec93 Santi Raffa
      for os in mydict["osparams_private_cluster"]:
1801 a5efec93 Santi Raffa
        mydict["osparams_private_cluster"][os] = \
1802 a5efec93 Santi Raffa
          self.osparams_private_cluster[os].Unprivate()
1803 4d36fbf4 Michael Hanselmann
1804 4d36fbf4 Michael Hanselmann
    if self.tcpudp_port_pool is None:
1805 4d36fbf4 Michael Hanselmann
      tcpudp_port_pool = []
1806 4d36fbf4 Michael Hanselmann
    else:
1807 4d36fbf4 Michael Hanselmann
      tcpudp_port_pool = list(self.tcpudp_port_pool)
1808 4d36fbf4 Michael Hanselmann
1809 4d36fbf4 Michael Hanselmann
    mydict["tcpudp_port_pool"] = tcpudp_port_pool
1810 4d36fbf4 Michael Hanselmann
1811 319856a9 Michael Hanselmann
    return mydict
1812 319856a9 Michael Hanselmann
1813 319856a9 Michael Hanselmann
  @classmethod
1814 319856a9 Michael Hanselmann
  def FromDict(cls, val):
1815 319856a9 Michael Hanselmann
    """Custom function for cluster.
1816 319856a9 Michael Hanselmann

1817 319856a9 Michael Hanselmann
    """
1818 b60ae2ca Iustin Pop
    obj = super(Cluster, cls).FromDict(val)
1819 4d36fbf4 Michael Hanselmann
1820 4d36fbf4 Michael Hanselmann
    if obj.tcpudp_port_pool is None:
1821 4d36fbf4 Michael Hanselmann
      obj.tcpudp_port_pool = set()
1822 4d36fbf4 Michael Hanselmann
    elif not isinstance(obj.tcpudp_port_pool, set):
1823 319856a9 Michael Hanselmann
      obj.tcpudp_port_pool = set(obj.tcpudp_port_pool)
1824 4d36fbf4 Michael Hanselmann
1825 319856a9 Michael Hanselmann
    return obj
1826 319856a9 Michael Hanselmann
1827 8a147bba Renรฉ Nussbaumer
  def SimpleFillDP(self, diskparams):
1828 8a147bba Renรฉ Nussbaumer
    """Fill a given diskparams dict with cluster defaults.
1829 8a147bba Renรฉ Nussbaumer

1830 8a147bba Renรฉ Nussbaumer
    @param diskparams: The diskparams
1831 8a147bba Renรฉ Nussbaumer
    @return: The defaults dict
1832 8a147bba Renรฉ Nussbaumer

1833 8a147bba Renรฉ Nussbaumer
    """
1834 8a147bba Renรฉ Nussbaumer
    return FillDiskParams(self.diskparams, diskparams)
1835 8a147bba Renรฉ Nussbaumer
1836 d63479b5 Iustin Pop
  def GetHVDefaults(self, hypervisor, os_name=None, skip_keys=None):
1837 d63479b5 Iustin Pop
    """Get the default hypervisor parameters for the cluster.
1838 d63479b5 Iustin Pop

1839 d63479b5 Iustin Pop
    @param hypervisor: the hypervisor name
1840 d63479b5 Iustin Pop
    @param os_name: if specified, we'll also update the defaults for this OS
1841 d63479b5 Iustin Pop
    @param skip_keys: if passed, list of keys not to use
1842 d63479b5 Iustin Pop
    @return: the defaults dict
1843 d63479b5 Iustin Pop

1844 d63479b5 Iustin Pop
    """
1845 d63479b5 Iustin Pop
    if skip_keys is None:
1846 d63479b5 Iustin Pop
      skip_keys = []
1847 d63479b5 Iustin Pop
1848 d63479b5 Iustin Pop
    fill_stack = [self.hvparams.get(hypervisor, {})]
1849 d63479b5 Iustin Pop
    if os_name is not None:
1850 d63479b5 Iustin Pop
      os_hvp = self.os_hvp.get(os_name, {}).get(hypervisor, {})
1851 d63479b5 Iustin Pop
      fill_stack.append(os_hvp)
1852 d63479b5 Iustin Pop
1853 d63479b5 Iustin Pop
    ret_dict = {}
1854 d63479b5 Iustin Pop
    for o_dict in fill_stack:
1855 d63479b5 Iustin Pop
      ret_dict = FillDict(ret_dict, o_dict, skip_keys=skip_keys)
1856 d63479b5 Iustin Pop
1857 d63479b5 Iustin Pop
    return ret_dict
1858 d63479b5 Iustin Pop
1859 73e0328b Iustin Pop
  def SimpleFillHV(self, hv_name, os_name, hvparams, skip_globals=False):
1860 73e0328b Iustin Pop
    """Fill a given hvparams dict with cluster defaults.
1861 73e0328b Iustin Pop

1862 73e0328b Iustin Pop
    @type hv_name: string
1863 73e0328b Iustin Pop
    @param hv_name: the hypervisor to use
1864 73e0328b Iustin Pop
    @type os_name: string
1865 73e0328b Iustin Pop
    @param os_name: the OS to use for overriding the hypervisor defaults
1866 73e0328b Iustin Pop
    @type skip_globals: boolean
1867 73e0328b Iustin Pop
    @param skip_globals: if True, the global hypervisor parameters will
1868 73e0328b Iustin Pop
        not be filled
1869 73e0328b Iustin Pop
    @rtype: dict
1870 73e0328b Iustin Pop
    @return: a copy of the given hvparams with missing keys filled from
1871 73e0328b Iustin Pop
        the cluster defaults
1872 73e0328b Iustin Pop

1873 73e0328b Iustin Pop
    """
1874 73e0328b Iustin Pop
    if skip_globals:
1875 73e0328b Iustin Pop
      skip_keys = constants.HVC_GLOBALS
1876 73e0328b Iustin Pop
    else:
1877 73e0328b Iustin Pop
      skip_keys = []
1878 73e0328b Iustin Pop
1879 73e0328b Iustin Pop
    def_dict = self.GetHVDefaults(hv_name, os_name, skip_keys=skip_keys)
1880 73e0328b Iustin Pop
    return FillDict(def_dict, hvparams, skip_keys=skip_keys)
1881 d63479b5 Iustin Pop
1882 7736a5f2 Iustin Pop
  def FillHV(self, instance, skip_globals=False):
1883 73e0328b Iustin Pop
    """Fill an instance's hvparams dict with cluster defaults.
1884 5bf7b5cf Iustin Pop

1885 a2a24f4c Guido Trotter
    @type instance: L{objects.Instance}
1886 5bf7b5cf Iustin Pop
    @param instance: the instance parameter to fill
1887 7736a5f2 Iustin Pop
    @type skip_globals: boolean
1888 7736a5f2 Iustin Pop
    @param skip_globals: if True, the global hypervisor parameters will
1889 7736a5f2 Iustin Pop
        not be filled
1890 5bf7b5cf Iustin Pop
    @rtype: dict
1891 5bf7b5cf Iustin Pop
    @return: a copy of the instance's hvparams with missing keys filled from
1892 5bf7b5cf Iustin Pop
        the cluster defaults
1893 5bf7b5cf Iustin Pop

1894 5bf7b5cf Iustin Pop
    """
1895 73e0328b Iustin Pop
    return self.SimpleFillHV(instance.hypervisor, instance.os,
1896 73e0328b Iustin Pop
                             instance.hvparams, skip_globals)
1897 17463d22 Renรฉ Nussbaumer
1898 73e0328b Iustin Pop
  def SimpleFillBE(self, beparams):
1899 73e0328b Iustin Pop
    """Fill a given beparams dict with cluster defaults.
1900 73e0328b Iustin Pop

1901 06596a60 Guido Trotter
    @type beparams: dict
1902 06596a60 Guido Trotter
    @param beparams: the dict to fill
1903 73e0328b Iustin Pop
    @rtype: dict
1904 73e0328b Iustin Pop
    @return: a copy of the passed in beparams with missing keys filled
1905 73e0328b Iustin Pop
        from the cluster defaults
1906 73e0328b Iustin Pop

1907 73e0328b Iustin Pop
    """
1908 73e0328b Iustin Pop
    return FillDict(self.beparams.get(constants.PP_DEFAULT, {}), beparams)
1909 5bf7b5cf Iustin Pop
1910 5bf7b5cf Iustin Pop
  def FillBE(self, instance):
1911 73e0328b Iustin Pop
    """Fill an instance's beparams dict with cluster defaults.
1912 5bf7b5cf Iustin Pop

1913 a2a24f4c Guido Trotter
    @type instance: L{objects.Instance}
1914 5bf7b5cf Iustin Pop
    @param instance: the instance parameter to fill
1915 5bf7b5cf Iustin Pop
    @rtype: dict
1916 5bf7b5cf Iustin Pop
    @return: a copy of the instance's beparams with missing keys filled from
1917 5bf7b5cf Iustin Pop
        the cluster defaults
1918 5bf7b5cf Iustin Pop

1919 5bf7b5cf Iustin Pop
    """
1920 73e0328b Iustin Pop
    return self.SimpleFillBE(instance.beparams)
1921 73e0328b Iustin Pop
1922 73e0328b Iustin Pop
  def SimpleFillNIC(self, nicparams):
1923 73e0328b Iustin Pop
    """Fill a given nicparams dict with cluster defaults.
1924 73e0328b Iustin Pop

1925 06596a60 Guido Trotter
    @type nicparams: dict
1926 06596a60 Guido Trotter
    @param nicparams: the dict to fill
1927 73e0328b Iustin Pop
    @rtype: dict
1928 73e0328b Iustin Pop
    @return: a copy of the passed in nicparams with missing keys filled
1929 73e0328b Iustin Pop
        from the cluster defaults
1930 73e0328b Iustin Pop

1931 73e0328b Iustin Pop
    """
1932 73e0328b Iustin Pop
    return FillDict(self.nicparams.get(constants.PP_DEFAULT, {}), nicparams)
1933 5bf7b5cf Iustin Pop
1934 a5efec93 Santi Raffa
  def SimpleFillOS(self, os_name,
1935 a5efec93 Santi Raffa
                    os_params_public,
1936 a5efec93 Santi Raffa
                    os_params_private=None,
1937 a5efec93 Santi Raffa
                    os_params_secret=None):
1938 1bdcbbab Iustin Pop
    """Fill an instance's osparams dict with cluster defaults.
1939 1bdcbbab Iustin Pop

1940 1bdcbbab Iustin Pop
    @type os_name: string
1941 1bdcbbab Iustin Pop
    @param os_name: the OS name to use
1942 a5efec93 Santi Raffa
    @type os_params_public: dict
1943 a5efec93 Santi Raffa
    @param os_params_public: the dict to fill with default values
1944 a5efec93 Santi Raffa
    @type os_params_private: dict
1945 a5efec93 Santi Raffa
    @param os_params_private: the dict with private fields to fill
1946 a5efec93 Santi Raffa
                              with default values. Not passing this field
1947 a5efec93 Santi Raffa
                              results in no private fields being added to the
1948 a5efec93 Santi Raffa
                              return value. Private fields will be wrapped in
1949 a5efec93 Santi Raffa
                              L{Private} objects.
1950 a5efec93 Santi Raffa
    @type os_params_secret: dict
1951 a5efec93 Santi Raffa
    @param os_params_secret: the dict with secret fields to fill
1952 a5efec93 Santi Raffa
                             with default values. Not passing this field
1953 a5efec93 Santi Raffa
                             results in no secret fields being added to the
1954 a5efec93 Santi Raffa
                             return value. Private fields will be wrapped in
1955 a5efec93 Santi Raffa
                             L{Private} objects.
1956 1bdcbbab Iustin Pop
    @rtype: dict
1957 1bdcbbab Iustin Pop
    @return: a copy of the instance's osparams with missing keys filled from
1958 a5efec93 Santi Raffa
        the cluster defaults. Private and secret parameters are not included
1959 a5efec93 Santi Raffa
        unless the respective optional parameters are supplied.
1960 1bdcbbab Iustin Pop

1961 1bdcbbab Iustin Pop
    """
1962 1c4910f7 Jose A. Lopes
    if os_name is None:
1963 1c4910f7 Jose A. Lopes
      name_only = None
1964 1c4910f7 Jose A. Lopes
    else:
1965 1c4910f7 Jose A. Lopes
      name_only = OS.GetName(os_name)
1966 a5efec93 Santi Raffa
1967 a5efec93 Santi Raffa
    defaults_base_public = self.osparams.get(name_only, {})
1968 a5efec93 Santi Raffa
    defaults_public = FillDict(defaults_base_public,
1969 a5efec93 Santi Raffa
                               self.osparams.get(os_name, {}))
1970 a5efec93 Santi Raffa
    params_public = FillDict(defaults_public, os_params_public)
1971 a5efec93 Santi Raffa
1972 a5efec93 Santi Raffa
    if os_params_private is not None:
1973 a5efec93 Santi Raffa
      defaults_base_private = self.osparams_private_cluster.get(name_only, {})
1974 a5efec93 Santi Raffa
      defaults_private = FillDict(defaults_base_private,
1975 a5efec93 Santi Raffa
                                  self.osparams_private_cluster.get(os_name,
1976 a5efec93 Santi Raffa
                                                                    {}))
1977 a5efec93 Santi Raffa
      params_private = FillDict(defaults_private, os_params_private)
1978 a5efec93 Santi Raffa
    else:
1979 a5efec93 Santi Raffa
      params_private = {}
1980 a5efec93 Santi Raffa
1981 a5efec93 Santi Raffa
    if os_params_secret is not None:
1982 a5efec93 Santi Raffa
      # There can't be default secret settings, so there's nothing to be done.
1983 a5efec93 Santi Raffa
      params_secret = os_params_secret
1984 a5efec93 Santi Raffa
    else:
1985 a5efec93 Santi Raffa
      params_secret = {}
1986 a5efec93 Santi Raffa
1987 a5efec93 Santi Raffa
    # Enforce that the set of keys be distinct:
1988 a5efec93 Santi Raffa
    duplicate_keys = utils.GetRepeatedKeys(params_public,
1989 a5efec93 Santi Raffa
                                           params_private,
1990 a5efec93 Santi Raffa
                                           params_secret)
1991 a5efec93 Santi Raffa
    if not duplicate_keys:
1992 a5efec93 Santi Raffa
1993 a5efec93 Santi Raffa
      # Actually update them:
1994 a5efec93 Santi Raffa
      params_public.update(params_private)
1995 a5efec93 Santi Raffa
      params_public.update(params_secret)
1996 a5efec93 Santi Raffa
1997 a5efec93 Santi Raffa
      return params_public
1998 a5efec93 Santi Raffa
1999 a5efec93 Santi Raffa
    else:
2000 a5efec93 Santi Raffa
2001 a5efec93 Santi Raffa
      def formatter(keys):
2002 a5efec93 Santi Raffa
        return utils.CommaJoin(sorted(map(repr, keys))) if keys else "(none)"
2003 a5efec93 Santi Raffa
2004 a5efec93 Santi Raffa
      #Lose the values.
2005 a5efec93 Santi Raffa
      params_public = set(params_public)
2006 a5efec93 Santi Raffa
      params_private = set(params_private)
2007 a5efec93 Santi Raffa
      params_secret = set(params_secret)
2008 a5efec93 Santi Raffa
2009 a5efec93 Santi Raffa
      msg = """Cannot assign multiple values to OS parameters.
2010 a5efec93 Santi Raffa

2011 a5efec93 Santi Raffa
      Conflicting OS parameters that would have been set by this operation:
2012 a5efec93 Santi Raffa
      - at public visibility:  {public}
2013 a5efec93 Santi Raffa
      - at private visibility: {private}
2014 a5efec93 Santi Raffa
      - at secret visibility:  {secret}
2015 a5efec93 Santi Raffa
      """.format(dupes=formatter(duplicate_keys),
2016 a5efec93 Santi Raffa
                 public=formatter(params_public & duplicate_keys),
2017 a5efec93 Santi Raffa
                 private=formatter(params_private & duplicate_keys),
2018 a5efec93 Santi Raffa
                 secret=formatter(params_secret & duplicate_keys))
2019 a5efec93 Santi Raffa
      raise errors.OpPrereqError(msg)
2020 1bdcbbab Iustin Pop
2021 2da9f556 Renรฉ Nussbaumer
  @staticmethod
2022 2da9f556 Renรฉ Nussbaumer
  def SimpleFillHvState(hv_state):
2023 2da9f556 Renรฉ Nussbaumer
    """Fill an hv_state sub dict with cluster defaults.
2024 2da9f556 Renรฉ Nussbaumer

2025 2da9f556 Renรฉ Nussbaumer
    """
2026 2da9f556 Renรฉ Nussbaumer
    return FillDict(constants.HVST_DEFAULTS, hv_state)
2027 2da9f556 Renรฉ Nussbaumer
2028 2da9f556 Renรฉ Nussbaumer
  @staticmethod
2029 2da9f556 Renรฉ Nussbaumer
  def SimpleFillDiskState(disk_state):
2030 2da9f556 Renรฉ Nussbaumer
    """Fill an disk_state sub dict with cluster defaults.
2031 2da9f556 Renรฉ Nussbaumer

2032 2da9f556 Renรฉ Nussbaumer
    """
2033 2da9f556 Renรฉ Nussbaumer
    return FillDict(constants.DS_DEFAULTS, disk_state)
2034 2da9f556 Renรฉ Nussbaumer
2035 095e71aa Renรฉ Nussbaumer
  def FillND(self, node, nodegroup):
2036 ce523de1 Michael Hanselmann
    """Return filled out ndparams for L{objects.NodeGroup} and L{objects.Node}
2037 095e71aa Renรฉ Nussbaumer

2038 095e71aa Renรฉ Nussbaumer
    @type node: L{objects.Node}
2039 095e71aa Renรฉ Nussbaumer
    @param node: A Node object to fill
2040 095e71aa Renรฉ Nussbaumer
    @type nodegroup: L{objects.NodeGroup}
2041 095e71aa Renรฉ Nussbaumer
    @param nodegroup: A Node object to fill
2042 095e71aa Renรฉ Nussbaumer
    @return a copy of the node's ndparams with defaults filled
2043 095e71aa Renรฉ Nussbaumer

2044 095e71aa Renรฉ Nussbaumer
    """
2045 095e71aa Renรฉ Nussbaumer
    return self.SimpleFillND(nodegroup.FillND(node))
2046 095e71aa Renรฉ Nussbaumer
2047 6b2a2942 Petr Pudlak
  def FillNDGroup(self, nodegroup):
2048 6b2a2942 Petr Pudlak
    """Return filled out ndparams for just L{objects.NodeGroup}
2049 6b2a2942 Petr Pudlak

2050 6b2a2942 Petr Pudlak
    @type nodegroup: L{objects.NodeGroup}
2051 6b2a2942 Petr Pudlak
    @param nodegroup: A Node object to fill
2052 6b2a2942 Petr Pudlak
    @return a copy of the node group's ndparams with defaults filled
2053 6b2a2942 Petr Pudlak

2054 6b2a2942 Petr Pudlak
    """
2055 6b2a2942 Petr Pudlak
    return self.SimpleFillND(nodegroup.SimpleFillND({}))
2056 6b2a2942 Petr Pudlak
2057 095e71aa Renรฉ Nussbaumer
  def SimpleFillND(self, ndparams):
2058 095e71aa Renรฉ Nussbaumer
    """Fill a given ndparams dict with defaults.
2059 095e71aa Renรฉ Nussbaumer

2060 095e71aa Renรฉ Nussbaumer
    @type ndparams: dict
2061 095e71aa Renรฉ Nussbaumer
    @param ndparams: the dict to fill
2062 095e71aa Renรฉ Nussbaumer
    @rtype: dict
2063 095e71aa Renรฉ Nussbaumer
    @return: a copy of the passed in ndparams with missing keys filled
2064 095e71aa Renรฉ Nussbaumer
        from the cluster defaults
2065 095e71aa Renรฉ Nussbaumer

2066 095e71aa Renรฉ Nussbaumer
    """
2067 095e71aa Renรฉ Nussbaumer
    return FillDict(self.ndparams, ndparams)
2068 095e71aa Renรฉ Nussbaumer
2069 918eb80b Agata Murawska
  def SimpleFillIPolicy(self, ipolicy):
2070 918eb80b Agata Murawska
    """ Fill instance policy dict with defaults.
2071 918eb80b Agata Murawska

2072 918eb80b Agata Murawska
    @type ipolicy: dict
2073 918eb80b Agata Murawska
    @param ipolicy: the dict to fill
2074 918eb80b Agata Murawska
    @rtype: dict
2075 918eb80b Agata Murawska
    @return: a copy of passed ipolicy with missing keys filled from
2076 918eb80b Agata Murawska
      the cluster defaults
2077 918eb80b Agata Murawska

2078 918eb80b Agata Murawska
    """
2079 2cc673a3 Iustin Pop
    return FillIPolicy(self.ipolicy, ipolicy)
2080 918eb80b Agata Murawska
2081 ebe93784 Helga Velroyen
  def IsDiskTemplateEnabled(self, disk_template):
2082 ebe93784 Helga Velroyen
    """Checks if a particular disk template is enabled.
2083 ebe93784 Helga Velroyen

2084 ebe93784 Helga Velroyen
    """
2085 ebe93784 Helga Velroyen
    return utils.storage.IsDiskTemplateEnabled(
2086 ebe93784 Helga Velroyen
        disk_template, self.enabled_disk_templates)
2087 ebe93784 Helga Velroyen
2088 ebe93784 Helga Velroyen
  def IsFileStorageEnabled(self):
2089 ebe93784 Helga Velroyen
    """Checks if file storage is enabled.
2090 ebe93784 Helga Velroyen

2091 ebe93784 Helga Velroyen
    """
2092 ebe93784 Helga Velroyen
    return utils.storage.IsFileStorageEnabled(self.enabled_disk_templates)
2093 ebe93784 Helga Velroyen
2094 ebe93784 Helga Velroyen
  def IsSharedFileStorageEnabled(self):
2095 ebe93784 Helga Velroyen
    """Checks if shared file storage is enabled.
2096 ebe93784 Helga Velroyen

2097 ebe93784 Helga Velroyen
    """
2098 ebe93784 Helga Velroyen
    return utils.storage.IsSharedFileStorageEnabled(
2099 ebe93784 Helga Velroyen
        self.enabled_disk_templates)
2100 ebe93784 Helga Velroyen
2101 5c947f38 Iustin Pop
2102 96acbc09 Michael Hanselmann
class BlockDevStatus(ConfigObject):
2103 96acbc09 Michael Hanselmann
  """Config object representing the status of a block device."""
2104 96acbc09 Michael Hanselmann
  __slots__ = [
2105 96acbc09 Michael Hanselmann
    "dev_path",
2106 96acbc09 Michael Hanselmann
    "major",
2107 96acbc09 Michael Hanselmann
    "minor",
2108 96acbc09 Michael Hanselmann
    "sync_percent",
2109 96acbc09 Michael Hanselmann
    "estimated_time",
2110 96acbc09 Michael Hanselmann
    "is_degraded",
2111 f208978a Michael Hanselmann
    "ldisk_status",
2112 96acbc09 Michael Hanselmann
    ]
2113 96acbc09 Michael Hanselmann
2114 96acbc09 Michael Hanselmann
2115 2d76b580 Michael Hanselmann
class ImportExportStatus(ConfigObject):
2116 2d76b580 Michael Hanselmann
  """Config object representing the status of an import or export."""
2117 2d76b580 Michael Hanselmann
  __slots__ = [
2118 2d76b580 Michael Hanselmann
    "recent_output",
2119 2d76b580 Michael Hanselmann
    "listen_port",
2120 2d76b580 Michael Hanselmann
    "connected",
2121 c08d76f5 Michael Hanselmann
    "progress_mbytes",
2122 c08d76f5 Michael Hanselmann
    "progress_throughput",
2123 c08d76f5 Michael Hanselmann
    "progress_eta",
2124 c08d76f5 Michael Hanselmann
    "progress_percent",
2125 2d76b580 Michael Hanselmann
    "exit_status",
2126 2d76b580 Michael Hanselmann
    "error_message",
2127 2d76b580 Michael Hanselmann
    ] + _TIMESTAMPS
2128 2d76b580 Michael Hanselmann
2129 2d76b580 Michael Hanselmann
2130 eb630f50 Michael Hanselmann
class ImportExportOptions(ConfigObject):
2131 eb630f50 Michael Hanselmann
  """Options for import/export daemon
2132 eb630f50 Michael Hanselmann

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

2140 eb630f50 Michael Hanselmann
  """
2141 eb630f50 Michael Hanselmann
  __slots__ = [
2142 eb630f50 Michael Hanselmann
    "key_name",
2143 eb630f50 Michael Hanselmann
    "ca_pem",
2144 a5310c2a Michael Hanselmann
    "compress",
2145 af1d39b1 Michael Hanselmann
    "magic",
2146 855d2fc7 Michael Hanselmann
    "ipv6",
2147 4478301b Michael Hanselmann
    "connect_timeout",
2148 eb630f50 Michael Hanselmann
    ]
2149 eb630f50 Michael Hanselmann
2150 eb630f50 Michael Hanselmann
2151 18d750b9 Guido Trotter
class ConfdRequest(ConfigObject):
2152 18d750b9 Guido Trotter
  """Object holding a confd request.
2153 18d750b9 Guido Trotter

2154 18d750b9 Guido Trotter
  @ivar protocol: confd protocol version
2155 18d750b9 Guido Trotter
  @ivar type: confd query type
2156 18d750b9 Guido Trotter
  @ivar query: query request
2157 18d750b9 Guido Trotter
  @ivar rsalt: requested reply salt
2158 18d750b9 Guido Trotter

2159 18d750b9 Guido Trotter
  """
2160 18d750b9 Guido Trotter
  __slots__ = [
2161 18d750b9 Guido Trotter
    "protocol",
2162 18d750b9 Guido Trotter
    "type",
2163 18d750b9 Guido Trotter
    "query",
2164 18d750b9 Guido Trotter
    "rsalt",
2165 18d750b9 Guido Trotter
    ]
2166 18d750b9 Guido Trotter
2167 18d750b9 Guido Trotter
2168 18d750b9 Guido Trotter
class ConfdReply(ConfigObject):
2169 18d750b9 Guido Trotter
  """Object holding a confd reply.
2170 18d750b9 Guido Trotter

2171 18d750b9 Guido Trotter
  @ivar protocol: confd protocol version
2172 18d750b9 Guido Trotter
  @ivar status: reply status code (ok, error)
2173 18d750b9 Guido Trotter
  @ivar answer: confd query reply
2174 18d750b9 Guido Trotter
  @ivar serial: configuration serial number
2175 18d750b9 Guido Trotter

2176 18d750b9 Guido Trotter
  """
2177 18d750b9 Guido Trotter
  __slots__ = [
2178 18d750b9 Guido Trotter
    "protocol",
2179 18d750b9 Guido Trotter
    "status",
2180 18d750b9 Guido Trotter
    "answer",
2181 18d750b9 Guido Trotter
    "serial",
2182 18d750b9 Guido Trotter
    ]
2183 18d750b9 Guido Trotter
2184 18d750b9 Guido Trotter
2185 707f23b5 Michael Hanselmann
class QueryFieldDefinition(ConfigObject):
2186 707f23b5 Michael Hanselmann
  """Object holding a query field definition.
2187 707f23b5 Michael Hanselmann

2188 24d6d3e2 Michael Hanselmann
  @ivar name: Field name
2189 707f23b5 Michael Hanselmann
  @ivar title: Human-readable title
2190 707f23b5 Michael Hanselmann
  @ivar kind: Field type
2191 1ae17369 Michael Hanselmann
  @ivar doc: Human-readable description
2192 707f23b5 Michael Hanselmann

2193 707f23b5 Michael Hanselmann
  """
2194 707f23b5 Michael Hanselmann
  __slots__ = [
2195 707f23b5 Michael Hanselmann
    "name",
2196 707f23b5 Michael Hanselmann
    "title",
2197 707f23b5 Michael Hanselmann
    "kind",
2198 1ae17369 Michael Hanselmann
    "doc",
2199 707f23b5 Michael Hanselmann
    ]
2200 707f23b5 Michael Hanselmann
2201 707f23b5 Michael Hanselmann
2202 0538c375 Michael Hanselmann
class _QueryResponseBase(ConfigObject):
2203 0538c375 Michael Hanselmann
  __slots__ = [
2204 0538c375 Michael Hanselmann
    "fields",
2205 0538c375 Michael Hanselmann
    ]
2206 0538c375 Michael Hanselmann
2207 a5efec93 Santi Raffa
  def ToDict(self, _with_private=False):
2208 0538c375 Michael Hanselmann
    """Custom function for serializing.
2209 0538c375 Michael Hanselmann

2210 0538c375 Michael Hanselmann
    """
2211 0538c375 Michael Hanselmann
    mydict = super(_QueryResponseBase, self).ToDict()
2212 fe502d25 Iustin Pop
    mydict["fields"] = outils.ContainerToDicts(mydict["fields"])
2213 0538c375 Michael Hanselmann
    return mydict
2214 0538c375 Michael Hanselmann
2215 0538c375 Michael Hanselmann
  @classmethod
2216 0538c375 Michael Hanselmann
  def FromDict(cls, val):
2217 0538c375 Michael Hanselmann
    """Custom function for de-serializing.
2218 0538c375 Michael Hanselmann

2219 0538c375 Michael Hanselmann
    """
2220 0538c375 Michael Hanselmann
    obj = super(_QueryResponseBase, cls).FromDict(val)
2221 473ab806 Michael Hanselmann
    obj.fields = \
2222 fe502d25 Iustin Pop
      outils.ContainerFromDicts(obj.fields, list, QueryFieldDefinition)
2223 0538c375 Michael Hanselmann
    return obj
2224 0538c375 Michael Hanselmann
2225 0538c375 Michael Hanselmann
2226 0538c375 Michael Hanselmann
class QueryResponse(_QueryResponseBase):
2227 24d6d3e2 Michael Hanselmann
  """Object holding the response to a query.
2228 24d6d3e2 Michael Hanselmann

2229 24d6d3e2 Michael Hanselmann
  @ivar fields: List of L{QueryFieldDefinition} objects
2230 24d6d3e2 Michael Hanselmann
  @ivar data: Requested data
2231 24d6d3e2 Michael Hanselmann

2232 24d6d3e2 Michael Hanselmann
  """
2233 24d6d3e2 Michael Hanselmann
  __slots__ = [
2234 24d6d3e2 Michael Hanselmann
    "data",
2235 24d6d3e2 Michael Hanselmann
    ]
2236 24d6d3e2 Michael Hanselmann
2237 24d6d3e2 Michael Hanselmann
2238 24d6d3e2 Michael Hanselmann
class QueryFieldsRequest(ConfigObject):
2239 24d6d3e2 Michael Hanselmann
  """Object holding a request for querying available fields.
2240 24d6d3e2 Michael Hanselmann

2241 24d6d3e2 Michael Hanselmann
  """
2242 24d6d3e2 Michael Hanselmann
  __slots__ = [
2243 24d6d3e2 Michael Hanselmann
    "what",
2244 24d6d3e2 Michael Hanselmann
    "fields",
2245 24d6d3e2 Michael Hanselmann
    ]
2246 24d6d3e2 Michael Hanselmann
2247 24d6d3e2 Michael Hanselmann
2248 0538c375 Michael Hanselmann
class QueryFieldsResponse(_QueryResponseBase):
2249 24d6d3e2 Michael Hanselmann
  """Object holding the response to a query for fields.
2250 24d6d3e2 Michael Hanselmann

2251 24d6d3e2 Michael Hanselmann
  @ivar fields: List of L{QueryFieldDefinition} objects
2252 24d6d3e2 Michael Hanselmann

2253 24d6d3e2 Michael Hanselmann
  """
2254 5ae4945a Iustin Pop
  __slots__ = []
2255 24d6d3e2 Michael Hanselmann
2256 24d6d3e2 Michael Hanselmann
2257 6a1434d7 Andrea Spadaccini
class MigrationStatus(ConfigObject):
2258 6a1434d7 Andrea Spadaccini
  """Object holding the status of a migration.
2259 6a1434d7 Andrea Spadaccini

2260 6a1434d7 Andrea Spadaccini
  """
2261 6a1434d7 Andrea Spadaccini
  __slots__ = [
2262 6a1434d7 Andrea Spadaccini
    "status",
2263 6a1434d7 Andrea Spadaccini
    "transferred_ram",
2264 6a1434d7 Andrea Spadaccini
    "total_ram",
2265 6a1434d7 Andrea Spadaccini
    ]
2266 6a1434d7 Andrea Spadaccini
2267 6a1434d7 Andrea Spadaccini
2268 25ce3ec4 Michael Hanselmann
class InstanceConsole(ConfigObject):
2269 25ce3ec4 Michael Hanselmann
  """Object describing how to access the console of an instance.
2270 25ce3ec4 Michael Hanselmann

2271 25ce3ec4 Michael Hanselmann
  """
2272 25ce3ec4 Michael Hanselmann
  __slots__ = [
2273 25ce3ec4 Michael Hanselmann
    "instance",
2274 25ce3ec4 Michael Hanselmann
    "kind",
2275 25ce3ec4 Michael Hanselmann
    "message",
2276 25ce3ec4 Michael Hanselmann
    "host",
2277 25ce3ec4 Michael Hanselmann
    "port",
2278 25ce3ec4 Michael Hanselmann
    "user",
2279 25ce3ec4 Michael Hanselmann
    "command",
2280 25ce3ec4 Michael Hanselmann
    "display",
2281 25ce3ec4 Michael Hanselmann
    ]
2282 25ce3ec4 Michael Hanselmann
2283 25ce3ec4 Michael Hanselmann
  def Validate(self):
2284 25ce3ec4 Michael Hanselmann
    """Validates contents of this object.
2285 25ce3ec4 Michael Hanselmann

2286 25ce3ec4 Michael Hanselmann
    """
2287 25ce3ec4 Michael Hanselmann
    assert self.kind in constants.CONS_ALL, "Unknown console type"
2288 25ce3ec4 Michael Hanselmann
    assert self.instance, "Missing instance name"
2289 4d2cdb5a Andrea Spadaccini
    assert self.message or self.kind in [constants.CONS_SSH,
2290 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
2291 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_VNC]
2292 25ce3ec4 Michael Hanselmann
    assert self.host or self.kind == constants.CONS_MESSAGE
2293 25ce3ec4 Michael Hanselmann
    assert self.port or self.kind in [constants.CONS_MESSAGE,
2294 25ce3ec4 Michael Hanselmann
                                      constants.CONS_SSH]
2295 25ce3ec4 Michael Hanselmann
    assert self.user or self.kind in [constants.CONS_MESSAGE,
2296 4d2cdb5a Andrea Spadaccini
                                      constants.CONS_SPICE,
2297 25ce3ec4 Michael Hanselmann
                                      constants.CONS_VNC]
2298 25ce3ec4 Michael Hanselmann
    assert self.command or self.kind in [constants.CONS_MESSAGE,
2299 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
2300 25ce3ec4 Michael Hanselmann
                                         constants.CONS_VNC]
2301 25ce3ec4 Michael Hanselmann
    assert self.display or self.kind in [constants.CONS_MESSAGE,
2302 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
2303 25ce3ec4 Michael Hanselmann
                                         constants.CONS_SSH]
2304 25ce3ec4 Michael Hanselmann
2305 25ce3ec4 Michael Hanselmann
2306 8140e24f Dimitris Aragiorgis
class Network(TaggableObject):
2307 eaa4c57c Dimitris Aragiorgis
  """Object representing a network definition for ganeti.
2308 eaa4c57c Dimitris Aragiorgis

2309 eaa4c57c Dimitris Aragiorgis
  """
2310 eaa4c57c Dimitris Aragiorgis
  __slots__ = [
2311 eaa4c57c Dimitris Aragiorgis
    "name",
2312 eaa4c57c Dimitris Aragiorgis
    "serial_no",
2313 eaa4c57c Dimitris Aragiorgis
    "mac_prefix",
2314 eaa4c57c Dimitris Aragiorgis
    "network",
2315 eaa4c57c Dimitris Aragiorgis
    "network6",
2316 eaa4c57c Dimitris Aragiorgis
    "gateway",
2317 eaa4c57c Dimitris Aragiorgis
    "gateway6",
2318 eaa4c57c Dimitris Aragiorgis
    "reservations",
2319 eaa4c57c Dimitris Aragiorgis
    "ext_reservations",
2320 eaa4c57c Dimitris Aragiorgis
    ] + _TIMESTAMPS + _UUID
2321 eaa4c57c Dimitris Aragiorgis
2322 7e8f03e3 Dimitris Aragiorgis
  def HooksDict(self, prefix=""):
2323 d89168ff Guido Trotter
    """Export a dictionary used by hooks with a network's information.
2324 d89168ff Guido Trotter

2325 d89168ff Guido Trotter
    @type prefix: String
2326 d89168ff Guido Trotter
    @param prefix: Prefix to prepend to the dict entries
2327 d89168ff Guido Trotter

2328 d89168ff Guido Trotter
    """
2329 d89168ff Guido Trotter
    result = {
2330 7e8f03e3 Dimitris Aragiorgis
      "%sNETWORK_NAME" % prefix: self.name,
2331 d89168ff Guido Trotter
      "%sNETWORK_UUID" % prefix: self.uuid,
2332 5a76adf7 Dimitris Aragiorgis
      "%sNETWORK_TAGS" % prefix: " ".join(self.GetTags()),
2333 d89168ff Guido Trotter
    }
2334 d89168ff Guido Trotter
    if self.network:
2335 d89168ff Guido Trotter
      result["%sNETWORK_SUBNET" % prefix] = self.network
2336 d89168ff Guido Trotter
    if self.gateway:
2337 d89168ff Guido Trotter
      result["%sNETWORK_GATEWAY" % prefix] = self.gateway
2338 d89168ff Guido Trotter
    if self.network6:
2339 d89168ff Guido Trotter
      result["%sNETWORK_SUBNET6" % prefix] = self.network6
2340 d89168ff Guido Trotter
    if self.gateway6:
2341 d89168ff Guido Trotter
      result["%sNETWORK_GATEWAY6" % prefix] = self.gateway6
2342 d89168ff Guido Trotter
    if self.mac_prefix:
2343 d89168ff Guido Trotter
      result["%sNETWORK_MAC_PREFIX" % prefix] = self.mac_prefix
2344 d89168ff Guido Trotter
2345 d89168ff Guido Trotter
    return result
2346 d89168ff Guido Trotter
2347 5cfa6c37 Dimitris Aragiorgis
  @classmethod
2348 5cfa6c37 Dimitris Aragiorgis
  def FromDict(cls, val):
2349 5cfa6c37 Dimitris Aragiorgis
    """Custom function for networks.
2350 5cfa6c37 Dimitris Aragiorgis

2351 48616625 Dimitris Aragiorgis
    Remove deprecated network_type and family.
2352 5cfa6c37 Dimitris Aragiorgis

2353 5cfa6c37 Dimitris Aragiorgis
    """
2354 5cfa6c37 Dimitris Aragiorgis
    if "network_type" in val:
2355 5cfa6c37 Dimitris Aragiorgis
      del val["network_type"]
2356 48616625 Dimitris Aragiorgis
    if "family" in val:
2357 48616625 Dimitris Aragiorgis
      del val["family"]
2358 5cfa6c37 Dimitris Aragiorgis
    obj = super(Network, cls).FromDict(val)
2359 5cfa6c37 Dimitris Aragiorgis
    return obj
2360 5cfa6c37 Dimitris Aragiorgis
2361 eaa4c57c Dimitris Aragiorgis
2362 523170de Dimitris Aragiorgis
# need to inherit object in order to use super()
2363 523170de Dimitris Aragiorgis
class SerializableConfigParser(ConfigParser.SafeConfigParser, object):
2364 a8083063 Iustin Pop
  """Simple wrapper over ConfigParse that allows serialization.
2365 a8083063 Iustin Pop

2366 a8083063 Iustin Pop
  This class is basically ConfigParser.SafeConfigParser with two
2367 a8083063 Iustin Pop
  additional methods that allow it to serialize/unserialize to/from a
2368 a8083063 Iustin Pop
  buffer.
2369 a8083063 Iustin Pop

2370 a8083063 Iustin Pop
  """
2371 a8083063 Iustin Pop
  def Dumps(self):
2372 a8083063 Iustin Pop
    """Dump this instance and return the string representation."""
2373 a8083063 Iustin Pop
    buf = StringIO()
2374 a8083063 Iustin Pop
    self.write(buf)
2375 a8083063 Iustin Pop
    return buf.getvalue()
2376 a8083063 Iustin Pop
2377 b39bf4bb Guido Trotter
  @classmethod
2378 b39bf4bb Guido Trotter
  def Loads(cls, data):
2379 a8083063 Iustin Pop
    """Load data from a string."""
2380 a8083063 Iustin Pop
    buf = StringIO(data)
2381 b39bf4bb Guido Trotter
    cfp = cls()
2382 a8083063 Iustin Pop
    cfp.readfp(buf)
2383 a8083063 Iustin Pop
    return cfp
2384 59726e15 Bernardo Dal Seno
2385 523170de Dimitris Aragiorgis
  def get(self, section, option, **kwargs):
2386 523170de Dimitris Aragiorgis
    value = None
2387 523170de Dimitris Aragiorgis
    try:
2388 523170de Dimitris Aragiorgis
      value = super(SerializableConfigParser, self).get(section, option,
2389 523170de Dimitris Aragiorgis
                                                        **kwargs)
2390 523170de Dimitris Aragiorgis
      if value.lower() == constants.VALUE_NONE:
2391 523170de Dimitris Aragiorgis
        value = None
2392 523170de Dimitris Aragiorgis
    except ConfigParser.NoOptionError:
2393 ad55b2d4 Klaus Aehlig
      r = re.compile(r"(disk|nic)\d+_name|nic\d+_(network|vlan)")
2394 523170de Dimitris Aragiorgis
      match = r.match(option)
2395 523170de Dimitris Aragiorgis
      if match:
2396 523170de Dimitris Aragiorgis
        pass
2397 523170de Dimitris Aragiorgis
      else:
2398 523170de Dimitris Aragiorgis
        raise
2399 523170de Dimitris Aragiorgis
2400 523170de Dimitris Aragiorgis
    return value
2401 523170de Dimitris Aragiorgis
2402 59726e15 Bernardo Dal Seno
2403 59726e15 Bernardo Dal Seno
class LvmPvInfo(ConfigObject):
2404 59726e15 Bernardo Dal Seno
  """Information about an LVM physical volume (PV).
2405 59726e15 Bernardo Dal Seno

2406 59726e15 Bernardo Dal Seno
  @type name: string
2407 59726e15 Bernardo Dal Seno
  @ivar name: name of the PV
2408 59726e15 Bernardo Dal Seno
  @type vg_name: string
2409 59726e15 Bernardo Dal Seno
  @ivar vg_name: name of the volume group containing the PV
2410 59726e15 Bernardo Dal Seno
  @type size: float
2411 59726e15 Bernardo Dal Seno
  @ivar size: size of the PV in MiB
2412 59726e15 Bernardo Dal Seno
  @type free: float
2413 59726e15 Bernardo Dal Seno
  @ivar free: free space in the PV, in MiB
2414 59726e15 Bernardo Dal Seno
  @type attributes: string
2415 59726e15 Bernardo Dal Seno
  @ivar attributes: PV attributes
2416 b496abdb Bernardo Dal Seno
  @type lv_list: list of strings
2417 b496abdb Bernardo Dal Seno
  @ivar lv_list: names of the LVs hosted on the PV
2418 59726e15 Bernardo Dal Seno
  """
2419 59726e15 Bernardo Dal Seno
  __slots__ = [
2420 59726e15 Bernardo Dal Seno
    "name",
2421 59726e15 Bernardo Dal Seno
    "vg_name",
2422 59726e15 Bernardo Dal Seno
    "size",
2423 59726e15 Bernardo Dal Seno
    "free",
2424 59726e15 Bernardo Dal Seno
    "attributes",
2425 b496abdb Bernardo Dal Seno
    "lv_list"
2426 59726e15 Bernardo Dal Seno
    ]
2427 59726e15 Bernardo Dal Seno
2428 59726e15 Bernardo Dal Seno
  def IsEmpty(self):
2429 59726e15 Bernardo Dal Seno
    """Is this PV empty?
2430 59726e15 Bernardo Dal Seno

2431 59726e15 Bernardo Dal Seno
    """
2432 59726e15 Bernardo Dal Seno
    return self.size <= (self.free + 1)
2433 59726e15 Bernardo Dal Seno
2434 59726e15 Bernardo Dal Seno
  def IsAllocatable(self):
2435 59726e15 Bernardo Dal Seno
    """Is this PV allocatable?
2436 59726e15 Bernardo Dal Seno

2437 59726e15 Bernardo Dal Seno
    """
2438 59726e15 Bernardo Dal Seno
    return ("a" in self.attributes)