Statistics
| Branch: | Tag: | Revision:

root / lib / objects.py @ 63b4bb1e

History | View | Annotate | Download (56.7 kB)

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

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

27 a8083063 Iustin Pop
"""
28 a8083063 Iustin Pop
29 0007f3ab Andrea Spadaccini
# pylint: disable=E0203,W0201,R0902
30 6c881c52 Iustin Pop
31 6c881c52 Iustin Pop
# E0203: Access to member %r before its definition, since we use
32 6c881c52 Iustin Pop
# objects.py which doesn't explicitely initialise its members
33 6c881c52 Iustin Pop
34 7260cfbe Iustin Pop
# W0201: Attribute '%s' defined outside __init__
35 a8083063 Iustin Pop
36 0007f3ab Andrea Spadaccini
# R0902: Allow instances of these objects to have more than 20 attributes
37 0007f3ab Andrea Spadaccini
38 a8083063 Iustin Pop
import ConfigParser
39 5c947f38 Iustin Pop
import re
40 5bf7b5cf Iustin Pop
import copy
41 e11a1b77 Adeodato Simo
import time
42 d5835922 Michael Hanselmann
from cStringIO import StringIO
43 a8083063 Iustin Pop
44 a8083063 Iustin Pop
from ganeti import errors
45 5c947f38 Iustin Pop
from ganeti import constants
46 0007f3ab Andrea Spadaccini
from ganeti import netutils
47 32017174 Agata Murawska
from ganeti import utils
48 a8083063 Iustin Pop
49 f4c9af7a Guido Trotter
from socket import AF_INET
50 f4c9af7a Guido Trotter
51 a8083063 Iustin Pop
52 a8083063 Iustin Pop
__all__ = ["ConfigObject", "ConfigData", "NIC", "Disk", "Instance",
53 24a3707f Guido Trotter
           "OS", "Node", "NodeGroup", "Cluster", "FillDict"]
54 a8083063 Iustin Pop
55 d693c864 Iustin Pop
_TIMESTAMPS = ["ctime", "mtime"]
56 e1dcc53a Iustin Pop
_UUID = ["uuid"]
57 96acbc09 Michael Hanselmann
58 32017174 Agata Murawska
# constants used to create InstancePolicy dictionary
59 32017174 Agata Murawska
TISPECS_GROUP_TYPES = {
60 4f725341 Agata Murawska
  constants.ISPECS_MIN: constants.VTYPE_INT,
61 4f725341 Agata Murawska
  constants.ISPECS_MAX: constants.VTYPE_INT,
62 2cc673a3 Iustin Pop
  }
63 32017174 Agata Murawska
64 32017174 Agata Murawska
TISPECS_CLUSTER_TYPES = {
65 4f725341 Agata Murawska
  constants.ISPECS_MIN: constants.VTYPE_INT,
66 4f725341 Agata Murawska
  constants.ISPECS_MAX: constants.VTYPE_INT,
67 4f725341 Agata Murawska
  constants.ISPECS_STD: constants.VTYPE_INT,
68 32017174 Agata Murawska
  }
69 32017174 Agata Murawska
70 8d8d650c Michael Hanselmann
71 e11ddf13 Iustin Pop
def FillDict(defaults_dict, custom_dict, skip_keys=None):
72 29921401 Iustin Pop
  """Basic function to apply settings on top a default dict.
73 abe609b2 Guido Trotter

74 29921401 Iustin Pop
  @type defaults_dict: dict
75 29921401 Iustin Pop
  @param defaults_dict: dictionary holding the default values
76 29921401 Iustin Pop
  @type custom_dict: dict
77 29921401 Iustin Pop
  @param custom_dict: dictionary holding customized value
78 7736a5f2 Iustin Pop
  @type skip_keys: list
79 7736a5f2 Iustin Pop
  @param skip_keys: which keys not to fill
80 29921401 Iustin Pop
  @rtype: dict
81 29921401 Iustin Pop
  @return: dict with the 'full' values
82 abe609b2 Guido Trotter

83 29921401 Iustin Pop
  """
84 29921401 Iustin Pop
  ret_dict = copy.deepcopy(defaults_dict)
85 29921401 Iustin Pop
  ret_dict.update(custom_dict)
86 e11ddf13 Iustin Pop
  if skip_keys:
87 e11ddf13 Iustin Pop
    for k in skip_keys:
88 e11ddf13 Iustin Pop
      try:
89 e11ddf13 Iustin Pop
        del ret_dict[k]
90 e11ddf13 Iustin Pop
      except KeyError:
91 e11ddf13 Iustin Pop
        pass
92 29921401 Iustin Pop
  return ret_dict
93 a8083063 Iustin Pop
94 6e34b628 Guido Trotter
95 2cc673a3 Iustin Pop
def FillIPolicy(default_ipolicy, custom_ipolicy, skip_keys=None):
96 2cc673a3 Iustin Pop
  """Fills an instance policy with defaults.
97 918eb80b Agata Murawska

98 918eb80b Agata Murawska
  """
99 2cc673a3 Iustin Pop
  assert frozenset(default_ipolicy.keys()) == constants.IPOLICY_ALL_KEYS
100 918eb80b Agata Murawska
  ret_dict = {}
101 12378fe3 Iustin Pop
  for key in constants.IPOLICY_ISPECS:
102 2cc673a3 Iustin Pop
    ret_dict[key] = FillDict(default_ipolicy[key],
103 2cc673a3 Iustin Pop
                             custom_ipolicy.get(key, {}),
104 918eb80b Agata Murawska
                             skip_keys=skip_keys)
105 2cc673a3 Iustin Pop
  # list items
106 d04c9d45 Iustin Pop
  for key in [constants.IPOLICY_DTS]:
107 2cc673a3 Iustin Pop
    ret_dict[key] = list(custom_ipolicy.get(key, default_ipolicy[key]))
108 ff6c5e55 Iustin Pop
  # other items which we know we can directly copy (immutables)
109 ff6c5e55 Iustin Pop
  for key in constants.IPOLICY_PARAMETERS:
110 ff6c5e55 Iustin Pop
    ret_dict[key] = custom_ipolicy.get(key, default_ipolicy[key])
111 2cc673a3 Iustin Pop
112 918eb80b Agata Murawska
  return ret_dict
113 918eb80b Agata Murawska
114 918eb80b Agata Murawska
115 6e34b628 Guido Trotter
def UpgradeGroupedParams(target, defaults):
116 6e34b628 Guido Trotter
  """Update all groups for the target parameter.
117 6e34b628 Guido Trotter

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

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

135 8c72ab2b Guido Trotter
  @type target: dict
136 8c72ab2b Guido Trotter
  @param target: "be" parameters dict
137 8c72ab2b Guido Trotter

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

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

154 bc5d0215 Andrea Spadaccini
  """
155 bc5d0215 Andrea Spadaccini
  if diskparams is None:
156 bc5d0215 Andrea Spadaccini
    result = constants.DISK_DT_DEFAULTS.copy()
157 bc5d0215 Andrea Spadaccini
  else:
158 bc5d0215 Andrea Spadaccini
    # Update the disk parameter values for each disk template.
159 bc5d0215 Andrea Spadaccini
    # The code iterates over constants.DISK_TEMPLATES because new templates
160 bc5d0215 Andrea Spadaccini
    # might have been added.
161 765ada2b Iustin Pop
    result = dict((dt, FillDict(constants.DISK_DT_DEFAULTS[dt],
162 765ada2b Iustin Pop
                                diskparams.get(dt, {})))
163 765ada2b Iustin Pop
                  for dt in constants.DISK_TEMPLATES)
164 bc5d0215 Andrea Spadaccini
165 bc5d0215 Andrea Spadaccini
  return result
166 bc5d0215 Andrea Spadaccini
167 bc5d0215 Andrea Spadaccini
168 2a27dac3 Iustin Pop
def UpgradeNDParams(ndparams):
169 2a27dac3 Iustin Pop
  """Upgrade ndparams structure.
170 2a27dac3 Iustin Pop

171 2a27dac3 Iustin Pop
  @type ndparams: dict
172 2a27dac3 Iustin Pop
  @param ndparams: disk parameters to upgrade
173 2a27dac3 Iustin Pop
  @rtype: dict
174 2a27dac3 Iustin Pop
  @return: the upgraded node parameters dict
175 2a27dac3 Iustin Pop

176 2a27dac3 Iustin Pop
  """
177 2a27dac3 Iustin Pop
  if ndparams is None:
178 2a27dac3 Iustin Pop
    ndparams = {}
179 2a27dac3 Iustin Pop
180 2a27dac3 Iustin Pop
  return FillDict(constants.NDC_DEFAULTS, ndparams)
181 2a27dac3 Iustin Pop
182 2a27dac3 Iustin Pop
183 918eb80b Agata Murawska
def MakeEmptyIPolicy():
184 918eb80b Agata Murawska
  """Create empty IPolicy dictionary.
185 918eb80b Agata Murawska

186 918eb80b Agata Murawska
  """
187 918eb80b Agata Murawska
  return dict([
188 2cc673a3 Iustin Pop
    (constants.ISPECS_MIN, {}),
189 2cc673a3 Iustin Pop
    (constants.ISPECS_MAX, {}),
190 2cc673a3 Iustin Pop
    (constants.ISPECS_STD, {}),
191 918eb80b Agata Murawska
    ])
192 918eb80b Agata Murawska
193 918eb80b Agata Murawska
194 32017174 Agata Murawska
def CreateIPolicyFromOpts(ispecs_mem_size=None,
195 32017174 Agata Murawska
                          ispecs_cpu_count=None,
196 32017174 Agata Murawska
                          ispecs_disk_count=None,
197 32017174 Agata Murawska
                          ispecs_disk_size=None,
198 32017174 Agata Murawska
                          ispecs_nic_count=None,
199 d04c9d45 Iustin Pop
                          ipolicy_disk_templates=None,
200 976b78ba Iustin Pop
                          ipolicy_vcpu_ratio=None,
201 32017174 Agata Murawska
                          group_ipolicy=False,
202 2cc673a3 Iustin Pop
                          allowed_values=None,
203 2cc673a3 Iustin Pop
                          fill_all=False):
204 2cc673a3 Iustin Pop
  """Creation of instance policy based on command line options.
205 2cc673a3 Iustin Pop

206 2cc673a3 Iustin Pop
  @param fill_all: whether for cluster policies we should ensure that
207 2cc673a3 Iustin Pop
    all values are filled
208 32017174 Agata Murawska

209 32017174 Agata Murawska

210 32017174 Agata Murawska
  """
211 32017174 Agata Murawska
  # prepare ipolicy dict
212 32017174 Agata Murawska
  ipolicy_transposed = {
213 4f725341 Agata Murawska
    constants.ISPEC_MEM_SIZE: ispecs_mem_size,
214 4f725341 Agata Murawska
    constants.ISPEC_CPU_COUNT: ispecs_cpu_count,
215 4f725341 Agata Murawska
    constants.ISPEC_DISK_COUNT: ispecs_disk_count,
216 4f725341 Agata Murawska
    constants.ISPEC_DISK_SIZE: ispecs_disk_size,
217 4f725341 Agata Murawska
    constants.ISPEC_NIC_COUNT: ispecs_nic_count,
218 32017174 Agata Murawska
    }
219 32017174 Agata Murawska
220 32017174 Agata Murawska
  # first, check that the values given are correct
221 32017174 Agata Murawska
  if group_ipolicy:
222 32017174 Agata Murawska
    forced_type = TISPECS_GROUP_TYPES
223 32017174 Agata Murawska
  else:
224 32017174 Agata Murawska
    forced_type = TISPECS_CLUSTER_TYPES
225 32017174 Agata Murawska
226 32017174 Agata Murawska
  for specs in ipolicy_transposed.values():
227 32017174 Agata Murawska
    utils.ForceDictType(specs, forced_type, allowed_values=allowed_values)
228 32017174 Agata Murawska
229 32017174 Agata Murawska
  # then transpose
230 32017174 Agata Murawska
  ipolicy_out = MakeEmptyIPolicy()
231 32017174 Agata Murawska
  for name, specs in ipolicy_transposed.iteritems():
232 32017174 Agata Murawska
    assert name in constants.ISPECS_PARAMETERS
233 32017174 Agata Murawska
    for key, val in specs.items(): # {min: .. ,max: .., std: ..}
234 32017174 Agata Murawska
      ipolicy_out[key][name] = val
235 32017174 Agata Murawska
236 976b78ba Iustin Pop
  # no filldict for non-dicts
237 976b78ba Iustin Pop
  if not group_ipolicy and fill_all:
238 976b78ba Iustin Pop
    if ipolicy_disk_templates is None:
239 976b78ba Iustin Pop
      ipolicy_disk_templates = constants.DISK_TEMPLATES
240 976b78ba Iustin Pop
    if ipolicy_vcpu_ratio is None:
241 976b78ba Iustin Pop
      ipolicy_vcpu_ratio = \
242 976b78ba Iustin Pop
        constants.IPOLICY_DEFAULTS[constants.IPOLICY_VCPU_RATIO]
243 d04c9d45 Iustin Pop
  if ipolicy_disk_templates is not None:
244 d04c9d45 Iustin Pop
    ipolicy_out[constants.IPOLICY_DTS] = list(ipolicy_disk_templates)
245 976b78ba Iustin Pop
  if ipolicy_vcpu_ratio is not None:
246 976b78ba Iustin Pop
    ipolicy_out[constants.IPOLICY_VCPU_RATIO] = ipolicy_vcpu_ratio
247 2cc673a3 Iustin Pop
248 57dc299a Iustin Pop
  assert not (frozenset(ipolicy_out.keys()) - constants.IPOLICY_ALL_KEYS)
249 57dc299a Iustin Pop
250 32017174 Agata Murawska
  return ipolicy_out
251 32017174 Agata Murawska
252 32017174 Agata Murawska
253 a8083063 Iustin Pop
class ConfigObject(object):
254 a8083063 Iustin Pop
  """A generic config object.
255 a8083063 Iustin Pop

256 a8083063 Iustin Pop
  It has the following properties:
257 a8083063 Iustin Pop

258 a8083063 Iustin Pop
    - provides somewhat safe recursive unpickling and pickling for its classes
259 a8083063 Iustin Pop
    - unset attributes which are defined in slots are always returned
260 a8083063 Iustin Pop
      as None instead of raising an error
261 a8083063 Iustin Pop

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

265 a8083063 Iustin Pop
  """
266 a8083063 Iustin Pop
  __slots__ = []
267 a8083063 Iustin Pop
268 a8083063 Iustin Pop
  def __init__(self, **kwargs):
269 319856a9 Michael Hanselmann
    for k, v in kwargs.iteritems():
270 319856a9 Michael Hanselmann
      setattr(self, k, v)
271 a8083063 Iustin Pop
272 a8083063 Iustin Pop
  def __getattr__(self, name):
273 adf385c7 Iustin Pop
    if name not in self._all_slots():
274 3ecf6786 Iustin Pop
      raise AttributeError("Invalid object attribute %s.%s" %
275 3ecf6786 Iustin Pop
                           (type(self).__name__, name))
276 a8083063 Iustin Pop
    return None
277 a8083063 Iustin Pop
278 a8083063 Iustin Pop
  def __setstate__(self, state):
279 adf385c7 Iustin Pop
    slots = self._all_slots()
280 a8083063 Iustin Pop
    for name in state:
281 adf385c7 Iustin Pop
      if name in slots:
282 a8083063 Iustin Pop
        setattr(self, name, state[name])
283 a8083063 Iustin Pop
284 adf385c7 Iustin Pop
  @classmethod
285 adf385c7 Iustin Pop
  def _all_slots(cls):
286 adf385c7 Iustin Pop
    """Compute the list of all declared slots for a class.
287 adf385c7 Iustin Pop

288 adf385c7 Iustin Pop
    """
289 adf385c7 Iustin Pop
    slots = []
290 adf385c7 Iustin Pop
    for parent in cls.__mro__:
291 adf385c7 Iustin Pop
      slots.extend(getattr(parent, "__slots__", []))
292 adf385c7 Iustin Pop
    return slots
293 adf385c7 Iustin Pop
294 415feb2e Renรฉ Nussbaumer
  #: Public getter for the defined slots
295 415feb2e Renรฉ Nussbaumer
  GetAllSlots = _all_slots
296 415feb2e Renรฉ Nussbaumer
297 ff9c047c Iustin Pop
  def ToDict(self):
298 ff9c047c Iustin Pop
    """Convert to a dict holding only standard python types.
299 ff9c047c Iustin Pop

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

306 ff9c047c Iustin Pop
    """
307 4c14965f Guido Trotter
    result = {}
308 adf385c7 Iustin Pop
    for name in self._all_slots():
309 4c14965f Guido Trotter
      value = getattr(self, name, None)
310 4c14965f Guido Trotter
      if value is not None:
311 4c14965f Guido Trotter
        result[name] = value
312 4c14965f Guido Trotter
    return result
313 4c14965f Guido Trotter
314 4c14965f Guido Trotter
  __getstate__ = ToDict
315 ff9c047c Iustin Pop
316 ff9c047c Iustin Pop
  @classmethod
317 ff9c047c Iustin Pop
  def FromDict(cls, val):
318 ff9c047c Iustin Pop
    """Create an object from a dictionary.
319 ff9c047c Iustin Pop

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

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

328 ff9c047c Iustin Pop
    """
329 ff9c047c Iustin Pop
    if not isinstance(val, dict):
330 ff9c047c Iustin Pop
      raise errors.ConfigurationError("Invalid object passed to FromDict:"
331 ff9c047c Iustin Pop
                                      " expected dict, got %s" % type(val))
332 319856a9 Michael Hanselmann
    val_str = dict([(str(k), v) for k, v in val.iteritems()])
333 b459a848 Andrea Spadaccini
    obj = cls(**val_str) # pylint: disable=W0142
334 ff9c047c Iustin Pop
    return obj
335 ff9c047c Iustin Pop
336 ff9c047c Iustin Pop
  @staticmethod
337 ff9c047c Iustin Pop
  def _ContainerToDicts(container):
338 ff9c047c Iustin Pop
    """Convert the elements of a container to standard python types.
339 ff9c047c Iustin Pop

340 ff9c047c Iustin Pop
    This method converts a container with elements derived from
341 ff9c047c Iustin Pop
    ConfigData to standard python types. If the container is a dict,
342 ff9c047c Iustin Pop
    we don't touch the keys, only the values.
343 ff9c047c Iustin Pop

344 ff9c047c Iustin Pop
    """
345 ff9c047c Iustin Pop
    if isinstance(container, dict):
346 ff9c047c Iustin Pop
      ret = dict([(k, v.ToDict()) for k, v in container.iteritems()])
347 ff9c047c Iustin Pop
    elif isinstance(container, (list, tuple, set, frozenset)):
348 ff9c047c Iustin Pop
      ret = [elem.ToDict() for elem in container]
349 ff9c047c Iustin Pop
    else:
350 ff9c047c Iustin Pop
      raise TypeError("Invalid type %s passed to _ContainerToDicts" %
351 ff9c047c Iustin Pop
                      type(container))
352 ff9c047c Iustin Pop
    return ret
353 ff9c047c Iustin Pop
354 ff9c047c Iustin Pop
  @staticmethod
355 ff9c047c Iustin Pop
  def _ContainerFromDicts(source, c_type, e_type):
356 ff9c047c Iustin Pop
    """Convert a container from standard python types.
357 ff9c047c Iustin Pop

358 ff9c047c Iustin Pop
    This method converts a container with standard python types to
359 ff9c047c Iustin Pop
    ConfigData objects. If the container is a dict, we don't touch the
360 ff9c047c Iustin Pop
    keys, only the values.
361 ff9c047c Iustin Pop

362 ff9c047c Iustin Pop
    """
363 ff9c047c Iustin Pop
    if not isinstance(c_type, type):
364 ff9c047c Iustin Pop
      raise TypeError("Container type %s passed to _ContainerFromDicts is"
365 ff9c047c Iustin Pop
                      " not a type" % type(c_type))
366 fe25a79a Guido Trotter
    if source is None:
367 fe25a79a Guido Trotter
      source = c_type()
368 ff9c047c Iustin Pop
    if c_type is dict:
369 ff9c047c Iustin Pop
      ret = dict([(k, e_type.FromDict(v)) for k, v in source.iteritems()])
370 ff9c047c Iustin Pop
    elif c_type in (list, tuple, set, frozenset):
371 ff9c047c Iustin Pop
      ret = c_type([e_type.FromDict(elem) for elem in source])
372 ff9c047c Iustin Pop
    else:
373 ff9c047c Iustin Pop
      raise TypeError("Invalid container type %s passed to"
374 ff9c047c Iustin Pop
                      " _ContainerFromDicts" % c_type)
375 ff9c047c Iustin Pop
    return ret
376 ff9c047c Iustin Pop
377 e8d563f3 Iustin Pop
  def Copy(self):
378 e8d563f3 Iustin Pop
    """Makes a deep copy of the current object and its children.
379 e8d563f3 Iustin Pop

380 e8d563f3 Iustin Pop
    """
381 e8d563f3 Iustin Pop
    dict_form = self.ToDict()
382 e8d563f3 Iustin Pop
    clone_obj = self.__class__.FromDict(dict_form)
383 e8d563f3 Iustin Pop
    return clone_obj
384 e8d563f3 Iustin Pop
385 ff9c047c Iustin Pop
  def __repr__(self):
386 ff9c047c Iustin Pop
    """Implement __repr__ for ConfigObjects."""
387 ff9c047c Iustin Pop
    return repr(self.ToDict())
388 ff9c047c Iustin Pop
389 560428be Guido Trotter
  def UpgradeConfig(self):
390 560428be Guido Trotter
    """Fill defaults for missing configuration values.
391 560428be Guido Trotter

392 90d726a8 Iustin Pop
    This method will be called at configuration load time, and its
393 90d726a8 Iustin Pop
    implementation will be object dependent.
394 560428be Guido Trotter

395 560428be Guido Trotter
    """
396 560428be Guido Trotter
    pass
397 560428be Guido Trotter
398 a8083063 Iustin Pop
399 ec29fe40 Iustin Pop
class TaggableObject(ConfigObject):
400 5c947f38 Iustin Pop
  """An generic class supporting tags.
401 5c947f38 Iustin Pop

402 5c947f38 Iustin Pop
  """
403 154b9580 Balazs Lecz
  __slots__ = ["tags"]
404 b5e5632e Iustin Pop
  VALID_TAG_RE = re.compile("^[\w.+*/:@-]+$")
405 2057f6c7 Iustin Pop
406 b5e5632e Iustin Pop
  @classmethod
407 b5e5632e Iustin Pop
  def ValidateTag(cls, tag):
408 5c947f38 Iustin Pop
    """Check if a tag is valid.
409 5c947f38 Iustin Pop

410 5c947f38 Iustin Pop
    If the tag is invalid, an errors.TagError will be raised. The
411 5c947f38 Iustin Pop
    function has no return value.
412 5c947f38 Iustin Pop

413 5c947f38 Iustin Pop
    """
414 5c947f38 Iustin Pop
    if not isinstance(tag, basestring):
415 3ecf6786 Iustin Pop
      raise errors.TagError("Invalid tag type (not a string)")
416 5c947f38 Iustin Pop
    if len(tag) > constants.MAX_TAG_LEN:
417 319856a9 Michael Hanselmann
      raise errors.TagError("Tag too long (>%d characters)" %
418 319856a9 Michael Hanselmann
                            constants.MAX_TAG_LEN)
419 5c947f38 Iustin Pop
    if not tag:
420 3ecf6786 Iustin Pop
      raise errors.TagError("Tags cannot be empty")
421 b5e5632e Iustin Pop
    if not cls.VALID_TAG_RE.match(tag):
422 3ecf6786 Iustin Pop
      raise errors.TagError("Tag contains invalid characters")
423 5c947f38 Iustin Pop
424 5c947f38 Iustin Pop
  def GetTags(self):
425 5c947f38 Iustin Pop
    """Return the tags list.
426 5c947f38 Iustin Pop

427 5c947f38 Iustin Pop
    """
428 5c947f38 Iustin Pop
    tags = getattr(self, "tags", None)
429 5c947f38 Iustin Pop
    if tags is None:
430 5c947f38 Iustin Pop
      tags = self.tags = set()
431 5c947f38 Iustin Pop
    return tags
432 5c947f38 Iustin Pop
433 5c947f38 Iustin Pop
  def AddTag(self, tag):
434 5c947f38 Iustin Pop
    """Add a new tag.
435 5c947f38 Iustin Pop

436 5c947f38 Iustin Pop
    """
437 5c947f38 Iustin Pop
    self.ValidateTag(tag)
438 5c947f38 Iustin Pop
    tags = self.GetTags()
439 5c947f38 Iustin Pop
    if len(tags) >= constants.MAX_TAGS_PER_OBJ:
440 3ecf6786 Iustin Pop
      raise errors.TagError("Too many tags")
441 5c947f38 Iustin Pop
    self.GetTags().add(tag)
442 5c947f38 Iustin Pop
443 5c947f38 Iustin Pop
  def RemoveTag(self, tag):
444 5c947f38 Iustin Pop
    """Remove a tag.
445 5c947f38 Iustin Pop

446 5c947f38 Iustin Pop
    """
447 5c947f38 Iustin Pop
    self.ValidateTag(tag)
448 5c947f38 Iustin Pop
    tags = self.GetTags()
449 5c947f38 Iustin Pop
    try:
450 5c947f38 Iustin Pop
      tags.remove(tag)
451 5c947f38 Iustin Pop
    except KeyError:
452 3ecf6786 Iustin Pop
      raise errors.TagError("Tag not found")
453 5c947f38 Iustin Pop
454 ff9c047c Iustin Pop
  def ToDict(self):
455 ff9c047c Iustin Pop
    """Taggable-object-specific conversion to standard python types.
456 ff9c047c Iustin Pop

457 ff9c047c Iustin Pop
    This replaces the tags set with a list.
458 ff9c047c Iustin Pop

459 ff9c047c Iustin Pop
    """
460 ff9c047c Iustin Pop
    bo = super(TaggableObject, self).ToDict()
461 ff9c047c Iustin Pop
462 ff9c047c Iustin Pop
    tags = bo.get("tags", None)
463 ff9c047c Iustin Pop
    if isinstance(tags, set):
464 ff9c047c Iustin Pop
      bo["tags"] = list(tags)
465 ff9c047c Iustin Pop
    return bo
466 ff9c047c Iustin Pop
467 ff9c047c Iustin Pop
  @classmethod
468 ff9c047c Iustin Pop
  def FromDict(cls, val):
469 ff9c047c Iustin Pop
    """Custom function for instances.
470 ff9c047c Iustin Pop

471 ff9c047c Iustin Pop
    """
472 ff9c047c Iustin Pop
    obj = super(TaggableObject, cls).FromDict(val)
473 ff9c047c Iustin Pop
    if hasattr(obj, "tags") and isinstance(obj.tags, list):
474 ff9c047c Iustin Pop
      obj.tags = set(obj.tags)
475 ff9c047c Iustin Pop
    return obj
476 ff9c047c Iustin Pop
477 5c947f38 Iustin Pop
478 061af273 Andrea Spadaccini
class MasterNetworkParameters(ConfigObject):
479 061af273 Andrea Spadaccini
  """Network configuration parameters for the master
480 061af273 Andrea Spadaccini

481 061af273 Andrea Spadaccini
  @ivar name: master name
482 061af273 Andrea Spadaccini
  @ivar ip: master IP
483 061af273 Andrea Spadaccini
  @ivar netmask: master netmask
484 061af273 Andrea Spadaccini
  @ivar netdev: master network device
485 061af273 Andrea Spadaccini
  @ivar ip_family: master IP family
486 061af273 Andrea Spadaccini

487 061af273 Andrea Spadaccini
  """
488 061af273 Andrea Spadaccini
  __slots__ = [
489 061af273 Andrea Spadaccini
    "name",
490 061af273 Andrea Spadaccini
    "ip",
491 061af273 Andrea Spadaccini
    "netmask",
492 061af273 Andrea Spadaccini
    "netdev",
493 061af273 Andrea Spadaccini
    "ip_family"
494 061af273 Andrea Spadaccini
    ]
495 061af273 Andrea Spadaccini
496 061af273 Andrea Spadaccini
497 a8083063 Iustin Pop
class ConfigData(ConfigObject):
498 a8083063 Iustin Pop
  """Top-level config object."""
499 3df43542 Guido Trotter
  __slots__ = [
500 3df43542 Guido Trotter
    "version",
501 3df43542 Guido Trotter
    "cluster",
502 3df43542 Guido Trotter
    "nodes",
503 3df43542 Guido Trotter
    "nodegroups",
504 3df43542 Guido Trotter
    "instances",
505 3df43542 Guido Trotter
    "serial_no",
506 3df43542 Guido Trotter
    ] + _TIMESTAMPS
507 a8083063 Iustin Pop
508 ff9c047c Iustin Pop
  def ToDict(self):
509 ff9c047c Iustin Pop
    """Custom function for top-level config data.
510 ff9c047c Iustin Pop

511 ff9c047c Iustin Pop
    This just replaces the list of instances, nodes and the cluster
512 ff9c047c Iustin Pop
    with standard python types.
513 ff9c047c Iustin Pop

514 ff9c047c Iustin Pop
    """
515 ff9c047c Iustin Pop
    mydict = super(ConfigData, self).ToDict()
516 ff9c047c Iustin Pop
    mydict["cluster"] = mydict["cluster"].ToDict()
517 3df43542 Guido Trotter
    for key in "nodes", "instances", "nodegroups":
518 ff9c047c Iustin Pop
      mydict[key] = self._ContainerToDicts(mydict[key])
519 ff9c047c Iustin Pop
520 ff9c047c Iustin Pop
    return mydict
521 ff9c047c Iustin Pop
522 ff9c047c Iustin Pop
  @classmethod
523 ff9c047c Iustin Pop
  def FromDict(cls, val):
524 ff9c047c Iustin Pop
    """Custom function for top-level config data
525 ff9c047c Iustin Pop

526 ff9c047c Iustin Pop
    """
527 ff9c047c Iustin Pop
    obj = super(ConfigData, cls).FromDict(val)
528 ff9c047c Iustin Pop
    obj.cluster = Cluster.FromDict(obj.cluster)
529 ff9c047c Iustin Pop
    obj.nodes = cls._ContainerFromDicts(obj.nodes, dict, Node)
530 ff9c047c Iustin Pop
    obj.instances = cls._ContainerFromDicts(obj.instances, dict, Instance)
531 3df43542 Guido Trotter
    obj.nodegroups = cls._ContainerFromDicts(obj.nodegroups, dict, NodeGroup)
532 ff9c047c Iustin Pop
    return obj
533 ff9c047c Iustin Pop
534 51cb1581 Luca Bigliardi
  def HasAnyDiskOfType(self, dev_type):
535 51cb1581 Luca Bigliardi
    """Check if in there is at disk of the given type in the configuration.
536 51cb1581 Luca Bigliardi

537 51cb1581 Luca Bigliardi
    @type dev_type: L{constants.LDS_BLOCK}
538 51cb1581 Luca Bigliardi
    @param dev_type: the type to look for
539 51cb1581 Luca Bigliardi
    @rtype: boolean
540 51cb1581 Luca Bigliardi
    @return: boolean indicating if a disk of the given type was found or not
541 51cb1581 Luca Bigliardi

542 51cb1581 Luca Bigliardi
    """
543 51cb1581 Luca Bigliardi
    for instance in self.instances.values():
544 51cb1581 Luca Bigliardi
      for disk in instance.disks:
545 51cb1581 Luca Bigliardi
        if disk.IsBasedOnDiskType(dev_type):
546 51cb1581 Luca Bigliardi
          return True
547 51cb1581 Luca Bigliardi
    return False
548 51cb1581 Luca Bigliardi
549 90d726a8 Iustin Pop
  def UpgradeConfig(self):
550 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
551 90d726a8 Iustin Pop

552 90d726a8 Iustin Pop
    """
553 90d726a8 Iustin Pop
    self.cluster.UpgradeConfig()
554 90d726a8 Iustin Pop
    for node in self.nodes.values():
555 90d726a8 Iustin Pop
      node.UpgradeConfig()
556 90d726a8 Iustin Pop
    for instance in self.instances.values():
557 90d726a8 Iustin Pop
      instance.UpgradeConfig()
558 3df43542 Guido Trotter
    if self.nodegroups is None:
559 3df43542 Guido Trotter
      self.nodegroups = {}
560 3df43542 Guido Trotter
    for nodegroup in self.nodegroups.values():
561 3df43542 Guido Trotter
      nodegroup.UpgradeConfig()
562 ee2f0ed4 Luca Bigliardi
    if self.cluster.drbd_usermode_helper is None:
563 ee2f0ed4 Luca Bigliardi
      # To decide if we set an helper let's check if at least one instance has
564 ee2f0ed4 Luca Bigliardi
      # a DRBD disk. This does not cover all the possible scenarios but it
565 ee2f0ed4 Luca Bigliardi
      # gives a good approximation.
566 ee2f0ed4 Luca Bigliardi
      if self.HasAnyDiskOfType(constants.LD_DRBD8):
567 ee2f0ed4 Luca Bigliardi
        self.cluster.drbd_usermode_helper = constants.DEFAULT_DRBD_HELPER
568 90d726a8 Iustin Pop
569 a8083063 Iustin Pop
570 a8083063 Iustin Pop
class NIC(ConfigObject):
571 a8083063 Iustin Pop
  """Config object representing a network card."""
572 1177d70e Guido Trotter
  __slots__ = ["mac", "ip", "nicparams"]
573 a8083063 Iustin Pop
574 255e19d4 Guido Trotter
  @classmethod
575 255e19d4 Guido Trotter
  def CheckParameterSyntax(cls, nicparams):
576 255e19d4 Guido Trotter
    """Check the given parameters for validity.
577 255e19d4 Guido Trotter

578 255e19d4 Guido Trotter
    @type nicparams:  dict
579 255e19d4 Guido Trotter
    @param nicparams: dictionary with parameter names/value
580 255e19d4 Guido Trotter
    @raise errors.ConfigurationError: when a parameter is not valid
581 255e19d4 Guido Trotter

582 255e19d4 Guido Trotter
    """
583 e8448672 Agata Murawska
    if (nicparams[constants.NIC_MODE] not in constants.NIC_VALID_MODES and
584 e8448672 Agata Murawska
        nicparams[constants.NIC_MODE] != constants.VALUE_AUTO):
585 255e19d4 Guido Trotter
      err = "Invalid nic mode: %s" % nicparams[constants.NIC_MODE]
586 255e19d4 Guido Trotter
      raise errors.ConfigurationError(err)
587 255e19d4 Guido Trotter
588 0c9d32c1 Guido Trotter
    if (nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED and
589 255e19d4 Guido Trotter
        not nicparams[constants.NIC_LINK]):
590 255e19d4 Guido Trotter
      err = "Missing bridged nic link"
591 255e19d4 Guido Trotter
      raise errors.ConfigurationError(err)
592 255e19d4 Guido Trotter
593 a8083063 Iustin Pop
594 a8083063 Iustin Pop
class Disk(ConfigObject):
595 a8083063 Iustin Pop
  """Config object representing a block device."""
596 a8083063 Iustin Pop
  __slots__ = ["dev_type", "logical_id", "physical_id",
597 bc5d0215 Andrea Spadaccini
               "children", "iv_name", "size", "mode", "params"]
598 a8083063 Iustin Pop
599 a8083063 Iustin Pop
  def CreateOnSecondary(self):
600 a8083063 Iustin Pop
    """Test if this device needs to be created on a secondary node."""
601 00fb8246 Michael Hanselmann
    return self.dev_type in (constants.LD_DRBD8, constants.LD_LV)
602 a8083063 Iustin Pop
603 a8083063 Iustin Pop
  def AssembleOnSecondary(self):
604 a8083063 Iustin Pop
    """Test if this device needs to be assembled on a secondary node."""
605 00fb8246 Michael Hanselmann
    return self.dev_type in (constants.LD_DRBD8, constants.LD_LV)
606 a8083063 Iustin Pop
607 a8083063 Iustin Pop
  def OpenOnSecondary(self):
608 a8083063 Iustin Pop
    """Test if this device needs to be opened on a secondary node."""
609 fe96220b Iustin Pop
    return self.dev_type in (constants.LD_LV,)
610 a8083063 Iustin Pop
611 222f2dd5 Iustin Pop
  def StaticDevPath(self):
612 222f2dd5 Iustin Pop
    """Return the device path if this device type has a static one.
613 222f2dd5 Iustin Pop

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

618 e51db2a6 Iustin Pop
    @warning: The path returned is not a normalized pathname; callers
619 e51db2a6 Iustin Pop
        should check that it is a valid path.
620 e51db2a6 Iustin Pop

621 222f2dd5 Iustin Pop
    """
622 222f2dd5 Iustin Pop
    if self.dev_type == constants.LD_LV:
623 222f2dd5 Iustin Pop
      return "/dev/%s/%s" % (self.logical_id[0], self.logical_id[1])
624 b6135bbc Apollon Oikonomopoulos
    elif self.dev_type == constants.LD_BLOCKDEV:
625 b6135bbc Apollon Oikonomopoulos
      return self.logical_id[1]
626 7181fba0 Constantinos Venetsanopoulos
    elif self.dev_type == constants.LD_RBD:
627 7181fba0 Constantinos Venetsanopoulos
      return "/dev/%s/%s" % (self.logical_id[0], self.logical_id[1])
628 222f2dd5 Iustin Pop
    return None
629 222f2dd5 Iustin Pop
630 fc1dc9d7 Iustin Pop
  def ChildrenNeeded(self):
631 fc1dc9d7 Iustin Pop
    """Compute the needed number of children for activation.
632 fc1dc9d7 Iustin Pop

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

637 fc1dc9d7 Iustin Pop
    Currently, only DRBD8 supports diskless activation (therefore we
638 fc1dc9d7 Iustin Pop
    return 0), for all other we keep the previous semantics and return
639 fc1dc9d7 Iustin Pop
    -1.
640 fc1dc9d7 Iustin Pop

641 fc1dc9d7 Iustin Pop
    """
642 fc1dc9d7 Iustin Pop
    if self.dev_type == constants.LD_DRBD8:
643 fc1dc9d7 Iustin Pop
      return 0
644 fc1dc9d7 Iustin Pop
    return -1
645 fc1dc9d7 Iustin Pop
646 51cb1581 Luca Bigliardi
  def IsBasedOnDiskType(self, dev_type):
647 51cb1581 Luca Bigliardi
    """Check if the disk or its children are based on the given type.
648 51cb1581 Luca Bigliardi

649 51cb1581 Luca Bigliardi
    @type dev_type: L{constants.LDS_BLOCK}
650 51cb1581 Luca Bigliardi
    @param dev_type: the type to look for
651 51cb1581 Luca Bigliardi
    @rtype: boolean
652 51cb1581 Luca Bigliardi
    @return: boolean indicating if a device of the given type was found or not
653 51cb1581 Luca Bigliardi

654 51cb1581 Luca Bigliardi
    """
655 51cb1581 Luca Bigliardi
    if self.children:
656 51cb1581 Luca Bigliardi
      for child in self.children:
657 51cb1581 Luca Bigliardi
        if child.IsBasedOnDiskType(dev_type):
658 51cb1581 Luca Bigliardi
          return True
659 51cb1581 Luca Bigliardi
    return self.dev_type == dev_type
660 51cb1581 Luca Bigliardi
661 a8083063 Iustin Pop
  def GetNodes(self, node):
662 a8083063 Iustin Pop
    """This function returns the nodes this device lives on.
663 a8083063 Iustin Pop

664 a8083063 Iustin Pop
    Given the node on which the parent of the device lives on (or, in
665 a8083063 Iustin Pop
    case of a top-level device, the primary node of the devices'
666 a8083063 Iustin Pop
    instance), this function will return a list of nodes on which this
667 a8083063 Iustin Pop
    devices needs to (or can) be assembled.
668 a8083063 Iustin Pop

669 a8083063 Iustin Pop
    """
670 b6135bbc Apollon Oikonomopoulos
    if self.dev_type in [constants.LD_LV, constants.LD_FILE,
671 7181fba0 Constantinos Venetsanopoulos
                         constants.LD_BLOCKDEV, constants.LD_RBD]:
672 a8083063 Iustin Pop
      result = [node]
673 a1f445d3 Iustin Pop
    elif self.dev_type in constants.LDS_DRBD:
674 a8083063 Iustin Pop
      result = [self.logical_id[0], self.logical_id[1]]
675 a8083063 Iustin Pop
      if node not in result:
676 3ecf6786 Iustin Pop
        raise errors.ConfigurationError("DRBD device passed unknown node")
677 a8083063 Iustin Pop
    else:
678 3ecf6786 Iustin Pop
      raise errors.ProgrammerError("Unhandled device type %s" % self.dev_type)
679 a8083063 Iustin Pop
    return result
680 a8083063 Iustin Pop
681 a8083063 Iustin Pop
  def ComputeNodeTree(self, parent_node):
682 a8083063 Iustin Pop
    """Compute the node/disk tree for this disk and its children.
683 a8083063 Iustin Pop

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

690 a8083063 Iustin Pop
    """
691 a8083063 Iustin Pop
    my_nodes = self.GetNodes(parent_node)
692 a8083063 Iustin Pop
    result = [(node, self) for node in my_nodes]
693 a8083063 Iustin Pop
    if not self.children:
694 a8083063 Iustin Pop
      # leaf device
695 a8083063 Iustin Pop
      return result
696 a8083063 Iustin Pop
    for node in my_nodes:
697 a8083063 Iustin Pop
      for child in self.children:
698 a8083063 Iustin Pop
        child_result = child.ComputeNodeTree(node)
699 a8083063 Iustin Pop
        if len(child_result) == 1:
700 a8083063 Iustin Pop
          # child (and all its descendants) is simple, doesn't split
701 a8083063 Iustin Pop
          # over multiple hosts, so we don't need to describe it, our
702 a8083063 Iustin Pop
          # own entry for this node describes it completely
703 a8083063 Iustin Pop
          continue
704 a8083063 Iustin Pop
        else:
705 a8083063 Iustin Pop
          # check if child nodes differ from my nodes; note that
706 a8083063 Iustin Pop
          # subdisk can differ from the child itself, and be instead
707 a8083063 Iustin Pop
          # one of its descendants
708 a8083063 Iustin Pop
          for subnode, subdisk in child_result:
709 a8083063 Iustin Pop
            if subnode not in my_nodes:
710 a8083063 Iustin Pop
              result.append((subnode, subdisk))
711 a8083063 Iustin Pop
            # otherwise child is under our own node, so we ignore this
712 a8083063 Iustin Pop
            # entry (but probably the other results in the list will
713 a8083063 Iustin Pop
            # be different)
714 a8083063 Iustin Pop
    return result
715 a8083063 Iustin Pop
716 6d33a6eb Iustin Pop
  def ComputeGrowth(self, amount):
717 6d33a6eb Iustin Pop
    """Compute the per-VG growth requirements.
718 6d33a6eb Iustin Pop

719 6d33a6eb Iustin Pop
    This only works for VG-based disks.
720 6d33a6eb Iustin Pop

721 6d33a6eb Iustin Pop
    @type amount: integer
722 6d33a6eb Iustin Pop
    @param amount: the desired increase in (user-visible) disk space
723 6d33a6eb Iustin Pop
    @rtype: dict
724 6d33a6eb Iustin Pop
    @return: a dictionary of volume-groups and the required size
725 6d33a6eb Iustin Pop

726 6d33a6eb Iustin Pop
    """
727 6d33a6eb Iustin Pop
    if self.dev_type == constants.LD_LV:
728 6d33a6eb Iustin Pop
      return {self.logical_id[0]: amount}
729 6d33a6eb Iustin Pop
    elif self.dev_type == constants.LD_DRBD8:
730 6d33a6eb Iustin Pop
      if self.children:
731 6d33a6eb Iustin Pop
        return self.children[0].ComputeGrowth(amount)
732 6d33a6eb Iustin Pop
      else:
733 6d33a6eb Iustin Pop
        return {}
734 6d33a6eb Iustin Pop
    else:
735 6d33a6eb Iustin Pop
      # Other disk types do not require VG space
736 6d33a6eb Iustin Pop
      return {}
737 6d33a6eb Iustin Pop
738 acec9d51 Iustin Pop
  def RecordGrow(self, amount):
739 acec9d51 Iustin Pop
    """Update the size of this disk after growth.
740 acec9d51 Iustin Pop

741 acec9d51 Iustin Pop
    This method recurses over the disks's children and updates their
742 acec9d51 Iustin Pop
    size correspondigly. The method needs to be kept in sync with the
743 acec9d51 Iustin Pop
    actual algorithms from bdev.
744 acec9d51 Iustin Pop

745 acec9d51 Iustin Pop
    """
746 7181fba0 Constantinos Venetsanopoulos
    if self.dev_type in (constants.LD_LV, constants.LD_FILE,
747 7181fba0 Constantinos Venetsanopoulos
                         constants.LD_RBD):
748 acec9d51 Iustin Pop
      self.size += amount
749 acec9d51 Iustin Pop
    elif self.dev_type == constants.LD_DRBD8:
750 acec9d51 Iustin Pop
      if self.children:
751 acec9d51 Iustin Pop
        self.children[0].RecordGrow(amount)
752 acec9d51 Iustin Pop
      self.size += amount
753 acec9d51 Iustin Pop
    else:
754 acec9d51 Iustin Pop
      raise errors.ProgrammerError("Disk.RecordGrow called for unsupported"
755 acec9d51 Iustin Pop
                                   " disk type %s" % self.dev_type)
756 acec9d51 Iustin Pop
757 735e1318 Michael Hanselmann
  def Update(self, size=None, mode=None):
758 735e1318 Michael Hanselmann
    """Apply changes to size and mode.
759 735e1318 Michael Hanselmann

760 735e1318 Michael Hanselmann
    """
761 735e1318 Michael Hanselmann
    if self.dev_type == constants.LD_DRBD8:
762 735e1318 Michael Hanselmann
      if self.children:
763 735e1318 Michael Hanselmann
        self.children[0].Update(size=size, mode=mode)
764 735e1318 Michael Hanselmann
    else:
765 735e1318 Michael Hanselmann
      assert not self.children
766 735e1318 Michael Hanselmann
767 735e1318 Michael Hanselmann
    if size is not None:
768 735e1318 Michael Hanselmann
      self.size = size
769 735e1318 Michael Hanselmann
    if mode is not None:
770 735e1318 Michael Hanselmann
      self.mode = mode
771 735e1318 Michael Hanselmann
772 a805ec18 Iustin Pop
  def UnsetSize(self):
773 a805ec18 Iustin Pop
    """Sets recursively the size to zero for the disk and its children.
774 a805ec18 Iustin Pop

775 a805ec18 Iustin Pop
    """
776 a805ec18 Iustin Pop
    if self.children:
777 a805ec18 Iustin Pop
      for child in self.children:
778 a805ec18 Iustin Pop
        child.UnsetSize()
779 a805ec18 Iustin Pop
    self.size = 0
780 a805ec18 Iustin Pop
781 0402302c Iustin Pop
  def SetPhysicalID(self, target_node, nodes_ip):
782 0402302c Iustin Pop
    """Convert the logical ID to the physical ID.
783 0402302c Iustin Pop

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

786 0402302c Iustin Pop
    The routine descends down and updates its children also, because
787 0402302c Iustin Pop
    this helps when the only the top device is passed to the remote
788 0402302c Iustin Pop
    node.
789 0402302c Iustin Pop

790 0402302c Iustin Pop
    Arguments:
791 0402302c Iustin Pop
      - target_node: the node we wish to configure for
792 0402302c Iustin Pop
      - nodes_ip: a mapping of node name to ip
793 0402302c Iustin Pop

794 0402302c Iustin Pop
    The target_node must exist in in nodes_ip, and must be one of the
795 0402302c Iustin Pop
    nodes in the logical ID for each of the DRBD devices encountered
796 0402302c Iustin Pop
    in the disk tree.
797 0402302c Iustin Pop

798 0402302c Iustin Pop
    """
799 0402302c Iustin Pop
    if self.children:
800 0402302c Iustin Pop
      for child in self.children:
801 0402302c Iustin Pop
        child.SetPhysicalID(target_node, nodes_ip)
802 0402302c Iustin Pop
803 0402302c Iustin Pop
    if self.logical_id is None and self.physical_id is not None:
804 0402302c Iustin Pop
      return
805 0402302c Iustin Pop
    if self.dev_type in constants.LDS_DRBD:
806 f9518d38 Iustin Pop
      pnode, snode, port, pminor, sminor, secret = self.logical_id
807 0402302c Iustin Pop
      if target_node not in (pnode, snode):
808 0402302c Iustin Pop
        raise errors.ConfigurationError("DRBD device not knowing node %s" %
809 0402302c Iustin Pop
                                        target_node)
810 0402302c Iustin Pop
      pnode_ip = nodes_ip.get(pnode, None)
811 0402302c Iustin Pop
      snode_ip = nodes_ip.get(snode, None)
812 0402302c Iustin Pop
      if pnode_ip is None or snode_ip is None:
813 0402302c Iustin Pop
        raise errors.ConfigurationError("Can't find primary or secondary node"
814 0402302c Iustin Pop
                                        " for %s" % str(self))
815 ffa1c0dc Iustin Pop
      p_data = (pnode_ip, port)
816 ffa1c0dc Iustin Pop
      s_data = (snode_ip, port)
817 0402302c Iustin Pop
      if pnode == target_node:
818 f9518d38 Iustin Pop
        self.physical_id = p_data + s_data + (pminor, secret)
819 0402302c Iustin Pop
      else: # it must be secondary, we tested above
820 f9518d38 Iustin Pop
        self.physical_id = s_data + p_data + (sminor, secret)
821 0402302c Iustin Pop
    else:
822 0402302c Iustin Pop
      self.physical_id = self.logical_id
823 0402302c Iustin Pop
    return
824 0402302c Iustin Pop
825 ff9c047c Iustin Pop
  def ToDict(self):
826 ff9c047c Iustin Pop
    """Disk-specific conversion to standard python types.
827 ff9c047c Iustin Pop

828 ff9c047c Iustin Pop
    This replaces the children lists of objects with lists of
829 ff9c047c Iustin Pop
    standard python types.
830 ff9c047c Iustin Pop

831 ff9c047c Iustin Pop
    """
832 ff9c047c Iustin Pop
    bo = super(Disk, self).ToDict()
833 ff9c047c Iustin Pop
834 ff9c047c Iustin Pop
    for attr in ("children",):
835 ff9c047c Iustin Pop
      alist = bo.get(attr, None)
836 ff9c047c Iustin Pop
      if alist:
837 ff9c047c Iustin Pop
        bo[attr] = self._ContainerToDicts(alist)
838 ff9c047c Iustin Pop
    return bo
839 ff9c047c Iustin Pop
840 ff9c047c Iustin Pop
  @classmethod
841 ff9c047c Iustin Pop
  def FromDict(cls, val):
842 ff9c047c Iustin Pop
    """Custom function for Disks
843 ff9c047c Iustin Pop

844 ff9c047c Iustin Pop
    """
845 ff9c047c Iustin Pop
    obj = super(Disk, cls).FromDict(val)
846 ff9c047c Iustin Pop
    if obj.children:
847 ff9c047c Iustin Pop
      obj.children = cls._ContainerFromDicts(obj.children, list, Disk)
848 ff9c047c Iustin Pop
    if obj.logical_id and isinstance(obj.logical_id, list):
849 ff9c047c Iustin Pop
      obj.logical_id = tuple(obj.logical_id)
850 ff9c047c Iustin Pop
    if obj.physical_id and isinstance(obj.physical_id, list):
851 ff9c047c Iustin Pop
      obj.physical_id = tuple(obj.physical_id)
852 f9518d38 Iustin Pop
    if obj.dev_type in constants.LDS_DRBD:
853 f9518d38 Iustin Pop
      # we need a tuple of length six here
854 f9518d38 Iustin Pop
      if len(obj.logical_id) < 6:
855 f9518d38 Iustin Pop
        obj.logical_id += (None,) * (6 - len(obj.logical_id))
856 ff9c047c Iustin Pop
    return obj
857 ff9c047c Iustin Pop
858 65a15336 Iustin Pop
  def __str__(self):
859 65a15336 Iustin Pop
    """Custom str() formatter for disks.
860 65a15336 Iustin Pop

861 65a15336 Iustin Pop
    """
862 65a15336 Iustin Pop
    if self.dev_type == constants.LD_LV:
863 e687ec01 Michael Hanselmann
      val = "<LogicalVolume(/dev/%s/%s" % self.logical_id
864 65a15336 Iustin Pop
    elif self.dev_type in constants.LDS_DRBD:
865 89f28b76 Iustin Pop
      node_a, node_b, port, minor_a, minor_b = self.logical_id[:5]
866 00fb8246 Michael Hanselmann
      val = "<DRBD8("
867 073ca59e Iustin Pop
      if self.physical_id is None:
868 073ca59e Iustin Pop
        phy = "unconfigured"
869 073ca59e Iustin Pop
      else:
870 073ca59e Iustin Pop
        phy = ("configured as %s:%s %s:%s" %
871 25a915d0 Iustin Pop
               (self.physical_id[0], self.physical_id[1],
872 25a915d0 Iustin Pop
                self.physical_id[2], self.physical_id[3]))
873 073ca59e Iustin Pop
874 89f28b76 Iustin Pop
      val += ("hosts=%s/%d-%s/%d, port=%s, %s, " %
875 89f28b76 Iustin Pop
              (node_a, minor_a, node_b, minor_b, port, phy))
876 65a15336 Iustin Pop
      if self.children and self.children.count(None) == 0:
877 65a15336 Iustin Pop
        val += "backend=%s, metadev=%s" % (self.children[0], self.children[1])
878 65a15336 Iustin Pop
      else:
879 65a15336 Iustin Pop
        val += "no local storage"
880 65a15336 Iustin Pop
    else:
881 65a15336 Iustin Pop
      val = ("<Disk(type=%s, logical_id=%s, physical_id=%s, children=%s" %
882 65a15336 Iustin Pop
             (self.dev_type, self.logical_id, self.physical_id, self.children))
883 65a15336 Iustin Pop
    if self.iv_name is None:
884 65a15336 Iustin Pop
      val += ", not visible"
885 65a15336 Iustin Pop
    else:
886 65a15336 Iustin Pop
      val += ", visible as /dev/%s" % self.iv_name
887 fd965830 Iustin Pop
    if isinstance(self.size, int):
888 fd965830 Iustin Pop
      val += ", size=%dm)>" % self.size
889 fd965830 Iustin Pop
    else:
890 fd965830 Iustin Pop
      val += ", size='%s')>" % (self.size,)
891 65a15336 Iustin Pop
    return val
892 65a15336 Iustin Pop
893 332d0e37 Iustin Pop
  def Verify(self):
894 332d0e37 Iustin Pop
    """Checks that this disk is correctly configured.
895 332d0e37 Iustin Pop

896 332d0e37 Iustin Pop
    """
897 7c4d6c7b Michael Hanselmann
    all_errors = []
898 332d0e37 Iustin Pop
    if self.mode not in constants.DISK_ACCESS_SET:
899 7c4d6c7b Michael Hanselmann
      all_errors.append("Disk access mode '%s' is invalid" % (self.mode, ))
900 7c4d6c7b Michael Hanselmann
    return all_errors
901 332d0e37 Iustin Pop
902 90d726a8 Iustin Pop
  def UpgradeConfig(self):
903 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
904 90d726a8 Iustin Pop

905 90d726a8 Iustin Pop
    """
906 90d726a8 Iustin Pop
    if self.children:
907 90d726a8 Iustin Pop
      for child in self.children:
908 90d726a8 Iustin Pop
        child.UpgradeConfig()
909 bc5d0215 Andrea Spadaccini
910 bc5d0215 Andrea Spadaccini
    if not self.params:
911 bc5d0215 Andrea Spadaccini
      self.params = constants.DISK_LD_DEFAULTS[self.dev_type].copy()
912 bc5d0215 Andrea Spadaccini
    else:
913 bc5d0215 Andrea Spadaccini
      self.params = FillDict(constants.DISK_LD_DEFAULTS[self.dev_type],
914 bc5d0215 Andrea Spadaccini
                             self.params)
915 90d726a8 Iustin Pop
    # add here config upgrade for this disk
916 90d726a8 Iustin Pop
917 a8083063 Iustin Pop
918 918eb80b Agata Murawska
class InstancePolicy(ConfigObject):
919 ffa339ca Iustin Pop
  """Config object representing instance policy limits dictionary.
920 918eb80b Agata Murawska

921 ffa339ca Iustin Pop

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

925 ffa339ca Iustin Pop
  """
926 918eb80b Agata Murawska
  @classmethod
927 918eb80b Agata Murawska
  def CheckParameterSyntax(cls, ipolicy):
928 918eb80b Agata Murawska
    """ Check the instance policy for validity.
929 918eb80b Agata Murawska

930 918eb80b Agata Murawska
    """
931 918eb80b Agata Murawska
    for param in constants.ISPECS_PARAMETERS:
932 918eb80b Agata Murawska
      InstancePolicy.CheckISpecSyntax(ipolicy, param)
933 d04c9d45 Iustin Pop
    if constants.IPOLICY_DTS in ipolicy:
934 d04c9d45 Iustin Pop
      InstancePolicy.CheckDiskTemplates(ipolicy[constants.IPOLICY_DTS])
935 ff6c5e55 Iustin Pop
    for key in constants.IPOLICY_PARAMETERS:
936 ff6c5e55 Iustin Pop
      if key in ipolicy:
937 ff6c5e55 Iustin Pop
        InstancePolicy.CheckParameter(key, ipolicy[key])
938 57dc299a Iustin Pop
    wrong_keys = frozenset(ipolicy.keys()) - constants.IPOLICY_ALL_KEYS
939 57dc299a Iustin Pop
    if wrong_keys:
940 57dc299a Iustin Pop
      raise errors.ConfigurationError("Invalid keys in ipolicy: %s" %
941 57dc299a Iustin Pop
                                      utils.CommaJoin(wrong_keys))
942 918eb80b Agata Murawska
943 918eb80b Agata Murawska
  @classmethod
944 918eb80b Agata Murawska
  def CheckISpecSyntax(cls, ipolicy, name):
945 918eb80b Agata Murawska
    """Check the instance policy for validity on a given key.
946 918eb80b Agata Murawska

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

950 918eb80b Agata Murawska
    @type ipolicy: dict
951 918eb80b Agata Murawska
    @param ipolicy: dictionary with min, max, std specs
952 918eb80b Agata Murawska
    @type name: string
953 918eb80b Agata Murawska
    @param name: what are the limits for
954 918eb80b Agata Murawska
    @raise errors.ConfigureError: when specs for given name are not valid
955 918eb80b Agata Murawska

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1414 095e71aa Renรฉ Nussbaumer
    """
1415 095e71aa Renรฉ Nussbaumer
    return self.SimpleFillND(node.ndparams)
1416 095e71aa Renรฉ Nussbaumer
1417 095e71aa Renรฉ Nussbaumer
  def SimpleFillND(self, ndparams):
1418 095e71aa Renรฉ Nussbaumer
    """Fill a given ndparams dict with defaults.
1419 095e71aa Renรฉ Nussbaumer

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

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

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

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

1584 0fbedb7a Michael Hanselmann
    """
1585 0fbedb7a Michael Hanselmann
    return self.enabled_hypervisors[0]
1586 0fbedb7a Michael Hanselmann
1587 319856a9 Michael Hanselmann
  def ToDict(self):
1588 319856a9 Michael Hanselmann
    """Custom function for cluster.
1589 319856a9 Michael Hanselmann

1590 319856a9 Michael Hanselmann
    """
1591 b60ae2ca Iustin Pop
    mydict = super(Cluster, self).ToDict()
1592 319856a9 Michael Hanselmann
    mydict["tcpudp_port_pool"] = list(self.tcpudp_port_pool)
1593 319856a9 Michael Hanselmann
    return mydict
1594 319856a9 Michael Hanselmann
1595 319856a9 Michael Hanselmann
  @classmethod
1596 319856a9 Michael Hanselmann
  def FromDict(cls, val):
1597 319856a9 Michael Hanselmann
    """Custom function for cluster.
1598 319856a9 Michael Hanselmann

1599 319856a9 Michael Hanselmann
    """
1600 b60ae2ca Iustin Pop
    obj = super(Cluster, cls).FromDict(val)
1601 319856a9 Michael Hanselmann
    if not isinstance(obj.tcpudp_port_pool, set):
1602 319856a9 Michael Hanselmann
      obj.tcpudp_port_pool = set(obj.tcpudp_port_pool)
1603 319856a9 Michael Hanselmann
    return obj
1604 319856a9 Michael Hanselmann
1605 d63479b5 Iustin Pop
  def GetHVDefaults(self, hypervisor, os_name=None, skip_keys=None):
1606 d63479b5 Iustin Pop
    """Get the default hypervisor parameters for the cluster.
1607 d63479b5 Iustin Pop

1608 d63479b5 Iustin Pop
    @param hypervisor: the hypervisor name
1609 d63479b5 Iustin Pop
    @param os_name: if specified, we'll also update the defaults for this OS
1610 d63479b5 Iustin Pop
    @param skip_keys: if passed, list of keys not to use
1611 d63479b5 Iustin Pop
    @return: the defaults dict
1612 d63479b5 Iustin Pop

1613 d63479b5 Iustin Pop
    """
1614 d63479b5 Iustin Pop
    if skip_keys is None:
1615 d63479b5 Iustin Pop
      skip_keys = []
1616 d63479b5 Iustin Pop
1617 d63479b5 Iustin Pop
    fill_stack = [self.hvparams.get(hypervisor, {})]
1618 d63479b5 Iustin Pop
    if os_name is not None:
1619 d63479b5 Iustin Pop
      os_hvp = self.os_hvp.get(os_name, {}).get(hypervisor, {})
1620 d63479b5 Iustin Pop
      fill_stack.append(os_hvp)
1621 d63479b5 Iustin Pop
1622 d63479b5 Iustin Pop
    ret_dict = {}
1623 d63479b5 Iustin Pop
    for o_dict in fill_stack:
1624 d63479b5 Iustin Pop
      ret_dict = FillDict(ret_dict, o_dict, skip_keys=skip_keys)
1625 d63479b5 Iustin Pop
1626 d63479b5 Iustin Pop
    return ret_dict
1627 d63479b5 Iustin Pop
1628 73e0328b Iustin Pop
  def SimpleFillHV(self, hv_name, os_name, hvparams, skip_globals=False):
1629 73e0328b Iustin Pop
    """Fill a given hvparams dict with cluster defaults.
1630 73e0328b Iustin Pop

1631 73e0328b Iustin Pop
    @type hv_name: string
1632 73e0328b Iustin Pop
    @param hv_name: the hypervisor to use
1633 73e0328b Iustin Pop
    @type os_name: string
1634 73e0328b Iustin Pop
    @param os_name: the OS to use for overriding the hypervisor defaults
1635 73e0328b Iustin Pop
    @type skip_globals: boolean
1636 73e0328b Iustin Pop
    @param skip_globals: if True, the global hypervisor parameters will
1637 73e0328b Iustin Pop
        not be filled
1638 73e0328b Iustin Pop
    @rtype: dict
1639 73e0328b Iustin Pop
    @return: a copy of the given hvparams with missing keys filled from
1640 73e0328b Iustin Pop
        the cluster defaults
1641 73e0328b Iustin Pop

1642 73e0328b Iustin Pop
    """
1643 73e0328b Iustin Pop
    if skip_globals:
1644 73e0328b Iustin Pop
      skip_keys = constants.HVC_GLOBALS
1645 73e0328b Iustin Pop
    else:
1646 73e0328b Iustin Pop
      skip_keys = []
1647 73e0328b Iustin Pop
1648 73e0328b Iustin Pop
    def_dict = self.GetHVDefaults(hv_name, os_name, skip_keys=skip_keys)
1649 73e0328b Iustin Pop
    return FillDict(def_dict, hvparams, skip_keys=skip_keys)
1650 d63479b5 Iustin Pop
1651 7736a5f2 Iustin Pop
  def FillHV(self, instance, skip_globals=False):
1652 73e0328b Iustin Pop
    """Fill an instance's hvparams dict with cluster defaults.
1653 5bf7b5cf Iustin Pop

1654 a2a24f4c Guido Trotter
    @type instance: L{objects.Instance}
1655 5bf7b5cf Iustin Pop
    @param instance: the instance parameter to fill
1656 7736a5f2 Iustin Pop
    @type skip_globals: boolean
1657 7736a5f2 Iustin Pop
    @param skip_globals: if True, the global hypervisor parameters will
1658 7736a5f2 Iustin Pop
        not be filled
1659 5bf7b5cf Iustin Pop
    @rtype: dict
1660 5bf7b5cf Iustin Pop
    @return: a copy of the instance's hvparams with missing keys filled from
1661 5bf7b5cf Iustin Pop
        the cluster defaults
1662 5bf7b5cf Iustin Pop

1663 5bf7b5cf Iustin Pop
    """
1664 73e0328b Iustin Pop
    return self.SimpleFillHV(instance.hypervisor, instance.os,
1665 73e0328b Iustin Pop
                             instance.hvparams, skip_globals)
1666 17463d22 Renรฉ Nussbaumer
1667 73e0328b Iustin Pop
  def SimpleFillBE(self, beparams):
1668 73e0328b Iustin Pop
    """Fill a given beparams dict with cluster defaults.
1669 73e0328b Iustin Pop

1670 06596a60 Guido Trotter
    @type beparams: dict
1671 06596a60 Guido Trotter
    @param beparams: the dict to fill
1672 73e0328b Iustin Pop
    @rtype: dict
1673 73e0328b Iustin Pop
    @return: a copy of the passed in beparams with missing keys filled
1674 73e0328b Iustin Pop
        from the cluster defaults
1675 73e0328b Iustin Pop

1676 73e0328b Iustin Pop
    """
1677 73e0328b Iustin Pop
    return FillDict(self.beparams.get(constants.PP_DEFAULT, {}), beparams)
1678 5bf7b5cf Iustin Pop
1679 5bf7b5cf Iustin Pop
  def FillBE(self, instance):
1680 73e0328b Iustin Pop
    """Fill an instance's beparams dict with cluster defaults.
1681 5bf7b5cf Iustin Pop

1682 a2a24f4c Guido Trotter
    @type instance: L{objects.Instance}
1683 5bf7b5cf Iustin Pop
    @param instance: the instance parameter to fill
1684 5bf7b5cf Iustin Pop
    @rtype: dict
1685 5bf7b5cf Iustin Pop
    @return: a copy of the instance's beparams with missing keys filled from
1686 5bf7b5cf Iustin Pop
        the cluster defaults
1687 5bf7b5cf Iustin Pop

1688 5bf7b5cf Iustin Pop
    """
1689 73e0328b Iustin Pop
    return self.SimpleFillBE(instance.beparams)
1690 73e0328b Iustin Pop
1691 73e0328b Iustin Pop
  def SimpleFillNIC(self, nicparams):
1692 73e0328b Iustin Pop
    """Fill a given nicparams dict with cluster defaults.
1693 73e0328b Iustin Pop

1694 06596a60 Guido Trotter
    @type nicparams: dict
1695 06596a60 Guido Trotter
    @param nicparams: the dict to fill
1696 73e0328b Iustin Pop
    @rtype: dict
1697 73e0328b Iustin Pop
    @return: a copy of the passed in nicparams with missing keys filled
1698 73e0328b Iustin Pop
        from the cluster defaults
1699 73e0328b Iustin Pop

1700 73e0328b Iustin Pop
    """
1701 73e0328b Iustin Pop
    return FillDict(self.nicparams.get(constants.PP_DEFAULT, {}), nicparams)
1702 5bf7b5cf Iustin Pop
1703 1bdcbbab Iustin Pop
  def SimpleFillOS(self, os_name, os_params):
1704 1bdcbbab Iustin Pop
    """Fill an instance's osparams dict with cluster defaults.
1705 1bdcbbab Iustin Pop

1706 1bdcbbab Iustin Pop
    @type os_name: string
1707 1bdcbbab Iustin Pop
    @param os_name: the OS name to use
1708 1bdcbbab Iustin Pop
    @type os_params: dict
1709 1bdcbbab Iustin Pop
    @param os_params: the dict to fill with default values
1710 1bdcbbab Iustin Pop
    @rtype: dict
1711 1bdcbbab Iustin Pop
    @return: a copy of the instance's osparams with missing keys filled from
1712 1bdcbbab Iustin Pop
        the cluster defaults
1713 1bdcbbab Iustin Pop

1714 1bdcbbab Iustin Pop
    """
1715 1bdcbbab Iustin Pop
    name_only = os_name.split("+", 1)[0]
1716 1bdcbbab Iustin Pop
    # base OS
1717 1bdcbbab Iustin Pop
    result = self.osparams.get(name_only, {})
1718 1bdcbbab Iustin Pop
    # OS with variant
1719 1bdcbbab Iustin Pop
    result = FillDict(result, self.osparams.get(os_name, {}))
1720 1bdcbbab Iustin Pop
    # specified params
1721 1bdcbbab Iustin Pop
    return FillDict(result, os_params)
1722 1bdcbbab Iustin Pop
1723 2da9f556 Renรฉ Nussbaumer
  @staticmethod
1724 2da9f556 Renรฉ Nussbaumer
  def SimpleFillHvState(hv_state):
1725 2da9f556 Renรฉ Nussbaumer
    """Fill an hv_state sub dict with cluster defaults.
1726 2da9f556 Renรฉ Nussbaumer

1727 2da9f556 Renรฉ Nussbaumer
    """
1728 2da9f556 Renรฉ Nussbaumer
    return FillDict(constants.HVST_DEFAULTS, hv_state)
1729 2da9f556 Renรฉ Nussbaumer
1730 2da9f556 Renรฉ Nussbaumer
  @staticmethod
1731 2da9f556 Renรฉ Nussbaumer
  def SimpleFillDiskState(disk_state):
1732 2da9f556 Renรฉ Nussbaumer
    """Fill an disk_state sub dict with cluster defaults.
1733 2da9f556 Renรฉ Nussbaumer

1734 2da9f556 Renรฉ Nussbaumer
    """
1735 2da9f556 Renรฉ Nussbaumer
    return FillDict(constants.DS_DEFAULTS, disk_state)
1736 2da9f556 Renรฉ Nussbaumer
1737 095e71aa Renรฉ Nussbaumer
  def FillND(self, node, nodegroup):
1738 ce523de1 Michael Hanselmann
    """Return filled out ndparams for L{objects.NodeGroup} and L{objects.Node}
1739 095e71aa Renรฉ Nussbaumer

1740 095e71aa Renรฉ Nussbaumer
    @type node: L{objects.Node}
1741 095e71aa Renรฉ Nussbaumer
    @param node: A Node object to fill
1742 095e71aa Renรฉ Nussbaumer
    @type nodegroup: L{objects.NodeGroup}
1743 095e71aa Renรฉ Nussbaumer
    @param nodegroup: A Node object to fill
1744 095e71aa Renรฉ Nussbaumer
    @return a copy of the node's ndparams with defaults filled
1745 095e71aa Renรฉ Nussbaumer

1746 095e71aa Renรฉ Nussbaumer
    """
1747 095e71aa Renรฉ Nussbaumer
    return self.SimpleFillND(nodegroup.FillND(node))
1748 095e71aa Renรฉ Nussbaumer
1749 095e71aa Renรฉ Nussbaumer
  def SimpleFillND(self, ndparams):
1750 095e71aa Renรฉ Nussbaumer
    """Fill a given ndparams dict with defaults.
1751 095e71aa Renรฉ Nussbaumer

1752 095e71aa Renรฉ Nussbaumer
    @type ndparams: dict
1753 095e71aa Renรฉ Nussbaumer
    @param ndparams: the dict to fill
1754 095e71aa Renรฉ Nussbaumer
    @rtype: dict
1755 095e71aa Renรฉ Nussbaumer
    @return: a copy of the passed in ndparams with missing keys filled
1756 095e71aa Renรฉ Nussbaumer
        from the cluster defaults
1757 095e71aa Renรฉ Nussbaumer

1758 095e71aa Renรฉ Nussbaumer
    """
1759 095e71aa Renรฉ Nussbaumer
    return FillDict(self.ndparams, ndparams)
1760 095e71aa Renรฉ Nussbaumer
1761 918eb80b Agata Murawska
  def SimpleFillIPolicy(self, ipolicy):
1762 918eb80b Agata Murawska
    """ Fill instance policy dict with defaults.
1763 918eb80b Agata Murawska

1764 918eb80b Agata Murawska
    @type ipolicy: dict
1765 918eb80b Agata Murawska
    @param ipolicy: the dict to fill
1766 918eb80b Agata Murawska
    @rtype: dict
1767 918eb80b Agata Murawska
    @return: a copy of passed ipolicy with missing keys filled from
1768 918eb80b Agata Murawska
      the cluster defaults
1769 918eb80b Agata Murawska

1770 918eb80b Agata Murawska
    """
1771 2cc673a3 Iustin Pop
    return FillIPolicy(self.ipolicy, ipolicy)
1772 918eb80b Agata Murawska
1773 5c947f38 Iustin Pop
1774 96acbc09 Michael Hanselmann
class BlockDevStatus(ConfigObject):
1775 96acbc09 Michael Hanselmann
  """Config object representing the status of a block device."""
1776 96acbc09 Michael Hanselmann
  __slots__ = [
1777 96acbc09 Michael Hanselmann
    "dev_path",
1778 96acbc09 Michael Hanselmann
    "major",
1779 96acbc09 Michael Hanselmann
    "minor",
1780 96acbc09 Michael Hanselmann
    "sync_percent",
1781 96acbc09 Michael Hanselmann
    "estimated_time",
1782 96acbc09 Michael Hanselmann
    "is_degraded",
1783 f208978a Michael Hanselmann
    "ldisk_status",
1784 96acbc09 Michael Hanselmann
    ]
1785 96acbc09 Michael Hanselmann
1786 96acbc09 Michael Hanselmann
1787 2d76b580 Michael Hanselmann
class ImportExportStatus(ConfigObject):
1788 2d76b580 Michael Hanselmann
  """Config object representing the status of an import or export."""
1789 2d76b580 Michael Hanselmann
  __slots__ = [
1790 2d76b580 Michael Hanselmann
    "recent_output",
1791 2d76b580 Michael Hanselmann
    "listen_port",
1792 2d76b580 Michael Hanselmann
    "connected",
1793 c08d76f5 Michael Hanselmann
    "progress_mbytes",
1794 c08d76f5 Michael Hanselmann
    "progress_throughput",
1795 c08d76f5 Michael Hanselmann
    "progress_eta",
1796 c08d76f5 Michael Hanselmann
    "progress_percent",
1797 2d76b580 Michael Hanselmann
    "exit_status",
1798 2d76b580 Michael Hanselmann
    "error_message",
1799 2d76b580 Michael Hanselmann
    ] + _TIMESTAMPS
1800 2d76b580 Michael Hanselmann
1801 2d76b580 Michael Hanselmann
1802 eb630f50 Michael Hanselmann
class ImportExportOptions(ConfigObject):
1803 eb630f50 Michael Hanselmann
  """Options for import/export daemon
1804 eb630f50 Michael Hanselmann

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

1812 eb630f50 Michael Hanselmann
  """
1813 eb630f50 Michael Hanselmann
  __slots__ = [
1814 eb630f50 Michael Hanselmann
    "key_name",
1815 eb630f50 Michael Hanselmann
    "ca_pem",
1816 a5310c2a Michael Hanselmann
    "compress",
1817 af1d39b1 Michael Hanselmann
    "magic",
1818 855d2fc7 Michael Hanselmann
    "ipv6",
1819 4478301b Michael Hanselmann
    "connect_timeout",
1820 eb630f50 Michael Hanselmann
    ]
1821 eb630f50 Michael Hanselmann
1822 eb630f50 Michael Hanselmann
1823 18d750b9 Guido Trotter
class ConfdRequest(ConfigObject):
1824 18d750b9 Guido Trotter
  """Object holding a confd request.
1825 18d750b9 Guido Trotter

1826 18d750b9 Guido Trotter
  @ivar protocol: confd protocol version
1827 18d750b9 Guido Trotter
  @ivar type: confd query type
1828 18d750b9 Guido Trotter
  @ivar query: query request
1829 18d750b9 Guido Trotter
  @ivar rsalt: requested reply salt
1830 18d750b9 Guido Trotter

1831 18d750b9 Guido Trotter
  """
1832 18d750b9 Guido Trotter
  __slots__ = [
1833 18d750b9 Guido Trotter
    "protocol",
1834 18d750b9 Guido Trotter
    "type",
1835 18d750b9 Guido Trotter
    "query",
1836 18d750b9 Guido Trotter
    "rsalt",
1837 18d750b9 Guido Trotter
    ]
1838 18d750b9 Guido Trotter
1839 18d750b9 Guido Trotter
1840 18d750b9 Guido Trotter
class ConfdReply(ConfigObject):
1841 18d750b9 Guido Trotter
  """Object holding a confd reply.
1842 18d750b9 Guido Trotter

1843 18d750b9 Guido Trotter
  @ivar protocol: confd protocol version
1844 18d750b9 Guido Trotter
  @ivar status: reply status code (ok, error)
1845 18d750b9 Guido Trotter
  @ivar answer: confd query reply
1846 18d750b9 Guido Trotter
  @ivar serial: configuration serial number
1847 18d750b9 Guido Trotter

1848 18d750b9 Guido Trotter
  """
1849 18d750b9 Guido Trotter
  __slots__ = [
1850 18d750b9 Guido Trotter
    "protocol",
1851 18d750b9 Guido Trotter
    "status",
1852 18d750b9 Guido Trotter
    "answer",
1853 18d750b9 Guido Trotter
    "serial",
1854 18d750b9 Guido Trotter
    ]
1855 18d750b9 Guido Trotter
1856 18d750b9 Guido Trotter
1857 707f23b5 Michael Hanselmann
class QueryFieldDefinition(ConfigObject):
1858 707f23b5 Michael Hanselmann
  """Object holding a query field definition.
1859 707f23b5 Michael Hanselmann

1860 24d6d3e2 Michael Hanselmann
  @ivar name: Field name
1861 707f23b5 Michael Hanselmann
  @ivar title: Human-readable title
1862 707f23b5 Michael Hanselmann
  @ivar kind: Field type
1863 1ae17369 Michael Hanselmann
  @ivar doc: Human-readable description
1864 707f23b5 Michael Hanselmann

1865 707f23b5 Michael Hanselmann
  """
1866 707f23b5 Michael Hanselmann
  __slots__ = [
1867 707f23b5 Michael Hanselmann
    "name",
1868 707f23b5 Michael Hanselmann
    "title",
1869 707f23b5 Michael Hanselmann
    "kind",
1870 1ae17369 Michael Hanselmann
    "doc",
1871 707f23b5 Michael Hanselmann
    ]
1872 707f23b5 Michael Hanselmann
1873 707f23b5 Michael Hanselmann
1874 0538c375 Michael Hanselmann
class _QueryResponseBase(ConfigObject):
1875 0538c375 Michael Hanselmann
  __slots__ = [
1876 0538c375 Michael Hanselmann
    "fields",
1877 0538c375 Michael Hanselmann
    ]
1878 0538c375 Michael Hanselmann
1879 0538c375 Michael Hanselmann
  def ToDict(self):
1880 0538c375 Michael Hanselmann
    """Custom function for serializing.
1881 0538c375 Michael Hanselmann

1882 0538c375 Michael Hanselmann
    """
1883 0538c375 Michael Hanselmann
    mydict = super(_QueryResponseBase, self).ToDict()
1884 0538c375 Michael Hanselmann
    mydict["fields"] = self._ContainerToDicts(mydict["fields"])
1885 0538c375 Michael Hanselmann
    return mydict
1886 0538c375 Michael Hanselmann
1887 0538c375 Michael Hanselmann
  @classmethod
1888 0538c375 Michael Hanselmann
  def FromDict(cls, val):
1889 0538c375 Michael Hanselmann
    """Custom function for de-serializing.
1890 0538c375 Michael Hanselmann

1891 0538c375 Michael Hanselmann
    """
1892 0538c375 Michael Hanselmann
    obj = super(_QueryResponseBase, cls).FromDict(val)
1893 0538c375 Michael Hanselmann
    obj.fields = cls._ContainerFromDicts(obj.fields, list, QueryFieldDefinition)
1894 0538c375 Michael Hanselmann
    return obj
1895 0538c375 Michael Hanselmann
1896 0538c375 Michael Hanselmann
1897 24d6d3e2 Michael Hanselmann
class QueryRequest(ConfigObject):
1898 24d6d3e2 Michael Hanselmann
  """Object holding a query request.
1899 24d6d3e2 Michael Hanselmann

1900 24d6d3e2 Michael Hanselmann
  """
1901 24d6d3e2 Michael Hanselmann
  __slots__ = [
1902 24d6d3e2 Michael Hanselmann
    "what",
1903 24d6d3e2 Michael Hanselmann
    "fields",
1904 2e5c33db Iustin Pop
    "qfilter",
1905 24d6d3e2 Michael Hanselmann
    ]
1906 24d6d3e2 Michael Hanselmann
1907 24d6d3e2 Michael Hanselmann
1908 0538c375 Michael Hanselmann
class QueryResponse(_QueryResponseBase):
1909 24d6d3e2 Michael Hanselmann
  """Object holding the response to a query.
1910 24d6d3e2 Michael Hanselmann

1911 24d6d3e2 Michael Hanselmann
  @ivar fields: List of L{QueryFieldDefinition} objects
1912 24d6d3e2 Michael Hanselmann
  @ivar data: Requested data
1913 24d6d3e2 Michael Hanselmann

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

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

1933 24d6d3e2 Michael Hanselmann
  @ivar fields: List of L{QueryFieldDefinition} objects
1934 24d6d3e2 Michael Hanselmann

1935 24d6d3e2 Michael Hanselmann
  """
1936 24d6d3e2 Michael Hanselmann
  __slots__ = [
1937 24d6d3e2 Michael Hanselmann
    ]
1938 24d6d3e2 Michael Hanselmann
1939 24d6d3e2 Michael Hanselmann
1940 6a1434d7 Andrea Spadaccini
class MigrationStatus(ConfigObject):
1941 6a1434d7 Andrea Spadaccini
  """Object holding the status of a migration.
1942 6a1434d7 Andrea Spadaccini

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

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

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

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

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