Statistics
| Branch: | Tag: | Revision:

root / lib / objects.py @ b8925b86

History | View | Annotate | Download (56.5 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 bc5d0215 Andrea Spadaccini
  @return: the upgraded disk parameters dit
153 bc5d0215 Andrea Spadaccini

154 bc5d0215 Andrea Spadaccini
  """
155 bc5d0215 Andrea Spadaccini
  result = dict()
156 bc5d0215 Andrea Spadaccini
  if diskparams is None:
157 bc5d0215 Andrea Spadaccini
    result = constants.DISK_DT_DEFAULTS.copy()
158 bc5d0215 Andrea Spadaccini
  else:
159 bc5d0215 Andrea Spadaccini
    # Update the disk parameter values for each disk template.
160 bc5d0215 Andrea Spadaccini
    # The code iterates over constants.DISK_TEMPLATES because new templates
161 bc5d0215 Andrea Spadaccini
    # might have been added.
162 bc5d0215 Andrea Spadaccini
    for template in constants.DISK_TEMPLATES:
163 bc5d0215 Andrea Spadaccini
      if template not in diskparams:
164 bc5d0215 Andrea Spadaccini
        result[template] = constants.DISK_DT_DEFAULTS[template].copy()
165 bc5d0215 Andrea Spadaccini
      else:
166 bc5d0215 Andrea Spadaccini
        result[template] = FillDict(constants.DISK_DT_DEFAULTS[template],
167 bc5d0215 Andrea Spadaccini
                                    diskparams[template])
168 bc5d0215 Andrea Spadaccini
169 bc5d0215 Andrea Spadaccini
  return result
170 bc5d0215 Andrea Spadaccini
171 bc5d0215 Andrea Spadaccini
172 918eb80b Agata Murawska
def MakeEmptyIPolicy():
173 918eb80b Agata Murawska
  """Create empty IPolicy dictionary.
174 918eb80b Agata Murawska

175 918eb80b Agata Murawska
  """
176 918eb80b Agata Murawska
  return dict([
177 2cc673a3 Iustin Pop
    (constants.ISPECS_MIN, {}),
178 2cc673a3 Iustin Pop
    (constants.ISPECS_MAX, {}),
179 2cc673a3 Iustin Pop
    (constants.ISPECS_STD, {}),
180 918eb80b Agata Murawska
    ])
181 918eb80b Agata Murawska
182 918eb80b Agata Murawska
183 32017174 Agata Murawska
def CreateIPolicyFromOpts(ispecs_mem_size=None,
184 32017174 Agata Murawska
                          ispecs_cpu_count=None,
185 32017174 Agata Murawska
                          ispecs_disk_count=None,
186 32017174 Agata Murawska
                          ispecs_disk_size=None,
187 32017174 Agata Murawska
                          ispecs_nic_count=None,
188 d04c9d45 Iustin Pop
                          ipolicy_disk_templates=None,
189 976b78ba Iustin Pop
                          ipolicy_vcpu_ratio=None,
190 32017174 Agata Murawska
                          group_ipolicy=False,
191 2cc673a3 Iustin Pop
                          allowed_values=None,
192 2cc673a3 Iustin Pop
                          fill_all=False):
193 2cc673a3 Iustin Pop
  """Creation of instance policy based on command line options.
194 2cc673a3 Iustin Pop

195 2cc673a3 Iustin Pop
  @param fill_all: whether for cluster policies we should ensure that
196 2cc673a3 Iustin Pop
    all values are filled
197 32017174 Agata Murawska

198 32017174 Agata Murawska

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

245 a8083063 Iustin Pop
  It has the following properties:
246 a8083063 Iustin Pop

247 a8083063 Iustin Pop
    - provides somewhat safe recursive unpickling and pickling for its classes
248 a8083063 Iustin Pop
    - unset attributes which are defined in slots are always returned
249 a8083063 Iustin Pop
      as None instead of raising an error
250 a8083063 Iustin Pop

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

254 a8083063 Iustin Pop
  """
255 a8083063 Iustin Pop
  __slots__ = []
256 a8083063 Iustin Pop
257 a8083063 Iustin Pop
  def __init__(self, **kwargs):
258 319856a9 Michael Hanselmann
    for k, v in kwargs.iteritems():
259 319856a9 Michael Hanselmann
      setattr(self, k, v)
260 a8083063 Iustin Pop
261 a8083063 Iustin Pop
  def __getattr__(self, name):
262 adf385c7 Iustin Pop
    if name not in self._all_slots():
263 3ecf6786 Iustin Pop
      raise AttributeError("Invalid object attribute %s.%s" %
264 3ecf6786 Iustin Pop
                           (type(self).__name__, name))
265 a8083063 Iustin Pop
    return None
266 a8083063 Iustin Pop
267 a8083063 Iustin Pop
  def __setstate__(self, state):
268 adf385c7 Iustin Pop
    slots = self._all_slots()
269 a8083063 Iustin Pop
    for name in state:
270 adf385c7 Iustin Pop
      if name in slots:
271 a8083063 Iustin Pop
        setattr(self, name, state[name])
272 a8083063 Iustin Pop
273 adf385c7 Iustin Pop
  @classmethod
274 adf385c7 Iustin Pop
  def _all_slots(cls):
275 adf385c7 Iustin Pop
    """Compute the list of all declared slots for a class.
276 adf385c7 Iustin Pop

277 adf385c7 Iustin Pop
    """
278 adf385c7 Iustin Pop
    slots = []
279 adf385c7 Iustin Pop
    for parent in cls.__mro__:
280 adf385c7 Iustin Pop
      slots.extend(getattr(parent, "__slots__", []))
281 adf385c7 Iustin Pop
    return slots
282 adf385c7 Iustin Pop
283 ff9c047c Iustin Pop
  def ToDict(self):
284 ff9c047c Iustin Pop
    """Convert to a dict holding only standard python types.
285 ff9c047c Iustin Pop

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

292 ff9c047c Iustin Pop
    """
293 4c14965f Guido Trotter
    result = {}
294 adf385c7 Iustin Pop
    for name in self._all_slots():
295 4c14965f Guido Trotter
      value = getattr(self, name, None)
296 4c14965f Guido Trotter
      if value is not None:
297 4c14965f Guido Trotter
        result[name] = value
298 4c14965f Guido Trotter
    return result
299 4c14965f Guido Trotter
300 4c14965f Guido Trotter
  __getstate__ = ToDict
301 ff9c047c Iustin Pop
302 ff9c047c Iustin Pop
  @classmethod
303 ff9c047c Iustin Pop
  def FromDict(cls, val):
304 ff9c047c Iustin Pop
    """Create an object from a dictionary.
305 ff9c047c Iustin Pop

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

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

314 ff9c047c Iustin Pop
    """
315 ff9c047c Iustin Pop
    if not isinstance(val, dict):
316 ff9c047c Iustin Pop
      raise errors.ConfigurationError("Invalid object passed to FromDict:"
317 ff9c047c Iustin Pop
                                      " expected dict, got %s" % type(val))
318 319856a9 Michael Hanselmann
    val_str = dict([(str(k), v) for k, v in val.iteritems()])
319 b459a848 Andrea Spadaccini
    obj = cls(**val_str) # pylint: disable=W0142
320 ff9c047c Iustin Pop
    return obj
321 ff9c047c Iustin Pop
322 ff9c047c Iustin Pop
  @staticmethod
323 ff9c047c Iustin Pop
  def _ContainerToDicts(container):
324 ff9c047c Iustin Pop
    """Convert the elements of a container to standard python types.
325 ff9c047c Iustin Pop

326 ff9c047c Iustin Pop
    This method converts a container with elements derived from
327 ff9c047c Iustin Pop
    ConfigData to standard python types. If the container is a dict,
328 ff9c047c Iustin Pop
    we don't touch the keys, only the values.
329 ff9c047c Iustin Pop

330 ff9c047c Iustin Pop
    """
331 ff9c047c Iustin Pop
    if isinstance(container, dict):
332 ff9c047c Iustin Pop
      ret = dict([(k, v.ToDict()) for k, v in container.iteritems()])
333 ff9c047c Iustin Pop
    elif isinstance(container, (list, tuple, set, frozenset)):
334 ff9c047c Iustin Pop
      ret = [elem.ToDict() for elem in container]
335 ff9c047c Iustin Pop
    else:
336 ff9c047c Iustin Pop
      raise TypeError("Invalid type %s passed to _ContainerToDicts" %
337 ff9c047c Iustin Pop
                      type(container))
338 ff9c047c Iustin Pop
    return ret
339 ff9c047c Iustin Pop
340 ff9c047c Iustin Pop
  @staticmethod
341 ff9c047c Iustin Pop
  def _ContainerFromDicts(source, c_type, e_type):
342 ff9c047c Iustin Pop
    """Convert a container from standard python types.
343 ff9c047c Iustin Pop

344 ff9c047c Iustin Pop
    This method converts a container with standard python types to
345 ff9c047c Iustin Pop
    ConfigData objects. If the container is a dict, we don't touch the
346 ff9c047c Iustin Pop
    keys, only the values.
347 ff9c047c Iustin Pop

348 ff9c047c Iustin Pop
    """
349 ff9c047c Iustin Pop
    if not isinstance(c_type, type):
350 ff9c047c Iustin Pop
      raise TypeError("Container type %s passed to _ContainerFromDicts is"
351 ff9c047c Iustin Pop
                      " not a type" % type(c_type))
352 fe25a79a Guido Trotter
    if source is None:
353 fe25a79a Guido Trotter
      source = c_type()
354 ff9c047c Iustin Pop
    if c_type is dict:
355 ff9c047c Iustin Pop
      ret = dict([(k, e_type.FromDict(v)) for k, v in source.iteritems()])
356 ff9c047c Iustin Pop
    elif c_type in (list, tuple, set, frozenset):
357 ff9c047c Iustin Pop
      ret = c_type([e_type.FromDict(elem) for elem in source])
358 ff9c047c Iustin Pop
    else:
359 ff9c047c Iustin Pop
      raise TypeError("Invalid container type %s passed to"
360 ff9c047c Iustin Pop
                      " _ContainerFromDicts" % c_type)
361 ff9c047c Iustin Pop
    return ret
362 ff9c047c Iustin Pop
363 e8d563f3 Iustin Pop
  def Copy(self):
364 e8d563f3 Iustin Pop
    """Makes a deep copy of the current object and its children.
365 e8d563f3 Iustin Pop

366 e8d563f3 Iustin Pop
    """
367 e8d563f3 Iustin Pop
    dict_form = self.ToDict()
368 e8d563f3 Iustin Pop
    clone_obj = self.__class__.FromDict(dict_form)
369 e8d563f3 Iustin Pop
    return clone_obj
370 e8d563f3 Iustin Pop
371 ff9c047c Iustin Pop
  def __repr__(self):
372 ff9c047c Iustin Pop
    """Implement __repr__ for ConfigObjects."""
373 ff9c047c Iustin Pop
    return repr(self.ToDict())
374 ff9c047c Iustin Pop
375 560428be Guido Trotter
  def UpgradeConfig(self):
376 560428be Guido Trotter
    """Fill defaults for missing configuration values.
377 560428be Guido Trotter

378 90d726a8 Iustin Pop
    This method will be called at configuration load time, and its
379 90d726a8 Iustin Pop
    implementation will be object dependent.
380 560428be Guido Trotter

381 560428be Guido Trotter
    """
382 560428be Guido Trotter
    pass
383 560428be Guido Trotter
384 a8083063 Iustin Pop
385 ec29fe40 Iustin Pop
class TaggableObject(ConfigObject):
386 5c947f38 Iustin Pop
  """An generic class supporting tags.
387 5c947f38 Iustin Pop

388 5c947f38 Iustin Pop
  """
389 154b9580 Balazs Lecz
  __slots__ = ["tags"]
390 b5e5632e Iustin Pop
  VALID_TAG_RE = re.compile("^[\w.+*/:@-]+$")
391 2057f6c7 Iustin Pop
392 b5e5632e Iustin Pop
  @classmethod
393 b5e5632e Iustin Pop
  def ValidateTag(cls, tag):
394 5c947f38 Iustin Pop
    """Check if a tag is valid.
395 5c947f38 Iustin Pop

396 5c947f38 Iustin Pop
    If the tag is invalid, an errors.TagError will be raised. The
397 5c947f38 Iustin Pop
    function has no return value.
398 5c947f38 Iustin Pop

399 5c947f38 Iustin Pop
    """
400 5c947f38 Iustin Pop
    if not isinstance(tag, basestring):
401 3ecf6786 Iustin Pop
      raise errors.TagError("Invalid tag type (not a string)")
402 5c947f38 Iustin Pop
    if len(tag) > constants.MAX_TAG_LEN:
403 319856a9 Michael Hanselmann
      raise errors.TagError("Tag too long (>%d characters)" %
404 319856a9 Michael Hanselmann
                            constants.MAX_TAG_LEN)
405 5c947f38 Iustin Pop
    if not tag:
406 3ecf6786 Iustin Pop
      raise errors.TagError("Tags cannot be empty")
407 b5e5632e Iustin Pop
    if not cls.VALID_TAG_RE.match(tag):
408 3ecf6786 Iustin Pop
      raise errors.TagError("Tag contains invalid characters")
409 5c947f38 Iustin Pop
410 5c947f38 Iustin Pop
  def GetTags(self):
411 5c947f38 Iustin Pop
    """Return the tags list.
412 5c947f38 Iustin Pop

413 5c947f38 Iustin Pop
    """
414 5c947f38 Iustin Pop
    tags = getattr(self, "tags", None)
415 5c947f38 Iustin Pop
    if tags is None:
416 5c947f38 Iustin Pop
      tags = self.tags = set()
417 5c947f38 Iustin Pop
    return tags
418 5c947f38 Iustin Pop
419 5c947f38 Iustin Pop
  def AddTag(self, tag):
420 5c947f38 Iustin Pop
    """Add a new tag.
421 5c947f38 Iustin Pop

422 5c947f38 Iustin Pop
    """
423 5c947f38 Iustin Pop
    self.ValidateTag(tag)
424 5c947f38 Iustin Pop
    tags = self.GetTags()
425 5c947f38 Iustin Pop
    if len(tags) >= constants.MAX_TAGS_PER_OBJ:
426 3ecf6786 Iustin Pop
      raise errors.TagError("Too many tags")
427 5c947f38 Iustin Pop
    self.GetTags().add(tag)
428 5c947f38 Iustin Pop
429 5c947f38 Iustin Pop
  def RemoveTag(self, tag):
430 5c947f38 Iustin Pop
    """Remove a tag.
431 5c947f38 Iustin Pop

432 5c947f38 Iustin Pop
    """
433 5c947f38 Iustin Pop
    self.ValidateTag(tag)
434 5c947f38 Iustin Pop
    tags = self.GetTags()
435 5c947f38 Iustin Pop
    try:
436 5c947f38 Iustin Pop
      tags.remove(tag)
437 5c947f38 Iustin Pop
    except KeyError:
438 3ecf6786 Iustin Pop
      raise errors.TagError("Tag not found")
439 5c947f38 Iustin Pop
440 ff9c047c Iustin Pop
  def ToDict(self):
441 ff9c047c Iustin Pop
    """Taggable-object-specific conversion to standard python types.
442 ff9c047c Iustin Pop

443 ff9c047c Iustin Pop
    This replaces the tags set with a list.
444 ff9c047c Iustin Pop

445 ff9c047c Iustin Pop
    """
446 ff9c047c Iustin Pop
    bo = super(TaggableObject, self).ToDict()
447 ff9c047c Iustin Pop
448 ff9c047c Iustin Pop
    tags = bo.get("tags", None)
449 ff9c047c Iustin Pop
    if isinstance(tags, set):
450 ff9c047c Iustin Pop
      bo["tags"] = list(tags)
451 ff9c047c Iustin Pop
    return bo
452 ff9c047c Iustin Pop
453 ff9c047c Iustin Pop
  @classmethod
454 ff9c047c Iustin Pop
  def FromDict(cls, val):
455 ff9c047c Iustin Pop
    """Custom function for instances.
456 ff9c047c Iustin Pop

457 ff9c047c Iustin Pop
    """
458 ff9c047c Iustin Pop
    obj = super(TaggableObject, cls).FromDict(val)
459 ff9c047c Iustin Pop
    if hasattr(obj, "tags") and isinstance(obj.tags, list):
460 ff9c047c Iustin Pop
      obj.tags = set(obj.tags)
461 ff9c047c Iustin Pop
    return obj
462 ff9c047c Iustin Pop
463 5c947f38 Iustin Pop
464 061af273 Andrea Spadaccini
class MasterNetworkParameters(ConfigObject):
465 061af273 Andrea Spadaccini
  """Network configuration parameters for the master
466 061af273 Andrea Spadaccini

467 061af273 Andrea Spadaccini
  @ivar name: master name
468 061af273 Andrea Spadaccini
  @ivar ip: master IP
469 061af273 Andrea Spadaccini
  @ivar netmask: master netmask
470 061af273 Andrea Spadaccini
  @ivar netdev: master network device
471 061af273 Andrea Spadaccini
  @ivar ip_family: master IP family
472 061af273 Andrea Spadaccini

473 061af273 Andrea Spadaccini
  """
474 061af273 Andrea Spadaccini
  __slots__ = [
475 061af273 Andrea Spadaccini
    "name",
476 061af273 Andrea Spadaccini
    "ip",
477 061af273 Andrea Spadaccini
    "netmask",
478 061af273 Andrea Spadaccini
    "netdev",
479 061af273 Andrea Spadaccini
    "ip_family"
480 061af273 Andrea Spadaccini
    ]
481 061af273 Andrea Spadaccini
482 061af273 Andrea Spadaccini
483 a8083063 Iustin Pop
class ConfigData(ConfigObject):
484 a8083063 Iustin Pop
  """Top-level config object."""
485 3df43542 Guido Trotter
  __slots__ = [
486 3df43542 Guido Trotter
    "version",
487 3df43542 Guido Trotter
    "cluster",
488 3df43542 Guido Trotter
    "nodes",
489 3df43542 Guido Trotter
    "nodegroups",
490 3df43542 Guido Trotter
    "instances",
491 3df43542 Guido Trotter
    "serial_no",
492 3df43542 Guido Trotter
    ] + _TIMESTAMPS
493 a8083063 Iustin Pop
494 ff9c047c Iustin Pop
  def ToDict(self):
495 ff9c047c Iustin Pop
    """Custom function for top-level config data.
496 ff9c047c Iustin Pop

497 ff9c047c Iustin Pop
    This just replaces the list of instances, nodes and the cluster
498 ff9c047c Iustin Pop
    with standard python types.
499 ff9c047c Iustin Pop

500 ff9c047c Iustin Pop
    """
501 ff9c047c Iustin Pop
    mydict = super(ConfigData, self).ToDict()
502 ff9c047c Iustin Pop
    mydict["cluster"] = mydict["cluster"].ToDict()
503 3df43542 Guido Trotter
    for key in "nodes", "instances", "nodegroups":
504 ff9c047c Iustin Pop
      mydict[key] = self._ContainerToDicts(mydict[key])
505 ff9c047c Iustin Pop
506 ff9c047c Iustin Pop
    return mydict
507 ff9c047c Iustin Pop
508 ff9c047c Iustin Pop
  @classmethod
509 ff9c047c Iustin Pop
  def FromDict(cls, val):
510 ff9c047c Iustin Pop
    """Custom function for top-level config data
511 ff9c047c Iustin Pop

512 ff9c047c Iustin Pop
    """
513 ff9c047c Iustin Pop
    obj = super(ConfigData, cls).FromDict(val)
514 ff9c047c Iustin Pop
    obj.cluster = Cluster.FromDict(obj.cluster)
515 ff9c047c Iustin Pop
    obj.nodes = cls._ContainerFromDicts(obj.nodes, dict, Node)
516 ff9c047c Iustin Pop
    obj.instances = cls._ContainerFromDicts(obj.instances, dict, Instance)
517 3df43542 Guido Trotter
    obj.nodegroups = cls._ContainerFromDicts(obj.nodegroups, dict, NodeGroup)
518 ff9c047c Iustin Pop
    return obj
519 ff9c047c Iustin Pop
520 51cb1581 Luca Bigliardi
  def HasAnyDiskOfType(self, dev_type):
521 51cb1581 Luca Bigliardi
    """Check if in there is at disk of the given type in the configuration.
522 51cb1581 Luca Bigliardi

523 51cb1581 Luca Bigliardi
    @type dev_type: L{constants.LDS_BLOCK}
524 51cb1581 Luca Bigliardi
    @param dev_type: the type to look for
525 51cb1581 Luca Bigliardi
    @rtype: boolean
526 51cb1581 Luca Bigliardi
    @return: boolean indicating if a disk of the given type was found or not
527 51cb1581 Luca Bigliardi

528 51cb1581 Luca Bigliardi
    """
529 51cb1581 Luca Bigliardi
    for instance in self.instances.values():
530 51cb1581 Luca Bigliardi
      for disk in instance.disks:
531 51cb1581 Luca Bigliardi
        if disk.IsBasedOnDiskType(dev_type):
532 51cb1581 Luca Bigliardi
          return True
533 51cb1581 Luca Bigliardi
    return False
534 51cb1581 Luca Bigliardi
535 90d726a8 Iustin Pop
  def UpgradeConfig(self):
536 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
537 90d726a8 Iustin Pop

538 90d726a8 Iustin Pop
    """
539 90d726a8 Iustin Pop
    self.cluster.UpgradeConfig()
540 90d726a8 Iustin Pop
    for node in self.nodes.values():
541 90d726a8 Iustin Pop
      node.UpgradeConfig()
542 90d726a8 Iustin Pop
    for instance in self.instances.values():
543 90d726a8 Iustin Pop
      instance.UpgradeConfig()
544 3df43542 Guido Trotter
    if self.nodegroups is None:
545 3df43542 Guido Trotter
      self.nodegroups = {}
546 3df43542 Guido Trotter
    for nodegroup in self.nodegroups.values():
547 3df43542 Guido Trotter
      nodegroup.UpgradeConfig()
548 ee2f0ed4 Luca Bigliardi
    if self.cluster.drbd_usermode_helper is None:
549 ee2f0ed4 Luca Bigliardi
      # To decide if we set an helper let's check if at least one instance has
550 ee2f0ed4 Luca Bigliardi
      # a DRBD disk. This does not cover all the possible scenarios but it
551 ee2f0ed4 Luca Bigliardi
      # gives a good approximation.
552 ee2f0ed4 Luca Bigliardi
      if self.HasAnyDiskOfType(constants.LD_DRBD8):
553 ee2f0ed4 Luca Bigliardi
        self.cluster.drbd_usermode_helper = constants.DEFAULT_DRBD_HELPER
554 90d726a8 Iustin Pop
555 a8083063 Iustin Pop
556 a8083063 Iustin Pop
class NIC(ConfigObject):
557 a8083063 Iustin Pop
  """Config object representing a network card."""
558 1177d70e Guido Trotter
  __slots__ = ["mac", "ip", "nicparams"]
559 a8083063 Iustin Pop
560 255e19d4 Guido Trotter
  @classmethod
561 255e19d4 Guido Trotter
  def CheckParameterSyntax(cls, nicparams):
562 255e19d4 Guido Trotter
    """Check the given parameters for validity.
563 255e19d4 Guido Trotter

564 255e19d4 Guido Trotter
    @type nicparams:  dict
565 255e19d4 Guido Trotter
    @param nicparams: dictionary with parameter names/value
566 255e19d4 Guido Trotter
    @raise errors.ConfigurationError: when a parameter is not valid
567 255e19d4 Guido Trotter

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

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

604 e51db2a6 Iustin Pop
    @warning: The path returned is not a normalized pathname; callers
605 e51db2a6 Iustin Pop
        should check that it is a valid path.
606 e51db2a6 Iustin Pop

607 222f2dd5 Iustin Pop
    """
608 222f2dd5 Iustin Pop
    if self.dev_type == constants.LD_LV:
609 222f2dd5 Iustin Pop
      return "/dev/%s/%s" % (self.logical_id[0], self.logical_id[1])
610 b6135bbc Apollon Oikonomopoulos
    elif self.dev_type == constants.LD_BLOCKDEV:
611 b6135bbc Apollon Oikonomopoulos
      return self.logical_id[1]
612 7181fba0 Constantinos Venetsanopoulos
    elif self.dev_type == constants.LD_RBD:
613 7181fba0 Constantinos Venetsanopoulos
      return "/dev/%s/%s" % (self.logical_id[0], self.logical_id[1])
614 222f2dd5 Iustin Pop
    return None
615 222f2dd5 Iustin Pop
616 fc1dc9d7 Iustin Pop
  def ChildrenNeeded(self):
617 fc1dc9d7 Iustin Pop
    """Compute the needed number of children for activation.
618 fc1dc9d7 Iustin Pop

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

623 fc1dc9d7 Iustin Pop
    Currently, only DRBD8 supports diskless activation (therefore we
624 fc1dc9d7 Iustin Pop
    return 0), for all other we keep the previous semantics and return
625 fc1dc9d7 Iustin Pop
    -1.
626 fc1dc9d7 Iustin Pop

627 fc1dc9d7 Iustin Pop
    """
628 fc1dc9d7 Iustin Pop
    if self.dev_type == constants.LD_DRBD8:
629 fc1dc9d7 Iustin Pop
      return 0
630 fc1dc9d7 Iustin Pop
    return -1
631 fc1dc9d7 Iustin Pop
632 51cb1581 Luca Bigliardi
  def IsBasedOnDiskType(self, dev_type):
633 51cb1581 Luca Bigliardi
    """Check if the disk or its children are based on the given type.
634 51cb1581 Luca Bigliardi

635 51cb1581 Luca Bigliardi
    @type dev_type: L{constants.LDS_BLOCK}
636 51cb1581 Luca Bigliardi
    @param dev_type: the type to look for
637 51cb1581 Luca Bigliardi
    @rtype: boolean
638 51cb1581 Luca Bigliardi
    @return: boolean indicating if a device of the given type was found or not
639 51cb1581 Luca Bigliardi

640 51cb1581 Luca Bigliardi
    """
641 51cb1581 Luca Bigliardi
    if self.children:
642 51cb1581 Luca Bigliardi
      for child in self.children:
643 51cb1581 Luca Bigliardi
        if child.IsBasedOnDiskType(dev_type):
644 51cb1581 Luca Bigliardi
          return True
645 51cb1581 Luca Bigliardi
    return self.dev_type == dev_type
646 51cb1581 Luca Bigliardi
647 a8083063 Iustin Pop
  def GetNodes(self, node):
648 a8083063 Iustin Pop
    """This function returns the nodes this device lives on.
649 a8083063 Iustin Pop

650 a8083063 Iustin Pop
    Given the node on which the parent of the device lives on (or, in
651 a8083063 Iustin Pop
    case of a top-level device, the primary node of the devices'
652 a8083063 Iustin Pop
    instance), this function will return a list of nodes on which this
653 a8083063 Iustin Pop
    devices needs to (or can) be assembled.
654 a8083063 Iustin Pop

655 a8083063 Iustin Pop
    """
656 b6135bbc Apollon Oikonomopoulos
    if self.dev_type in [constants.LD_LV, constants.LD_FILE,
657 7181fba0 Constantinos Venetsanopoulos
                         constants.LD_BLOCKDEV, constants.LD_RBD]:
658 a8083063 Iustin Pop
      result = [node]
659 a1f445d3 Iustin Pop
    elif self.dev_type in constants.LDS_DRBD:
660 a8083063 Iustin Pop
      result = [self.logical_id[0], self.logical_id[1]]
661 a8083063 Iustin Pop
      if node not in result:
662 3ecf6786 Iustin Pop
        raise errors.ConfigurationError("DRBD device passed unknown node")
663 a8083063 Iustin Pop
    else:
664 3ecf6786 Iustin Pop
      raise errors.ProgrammerError("Unhandled device type %s" % self.dev_type)
665 a8083063 Iustin Pop
    return result
666 a8083063 Iustin Pop
667 a8083063 Iustin Pop
  def ComputeNodeTree(self, parent_node):
668 a8083063 Iustin Pop
    """Compute the node/disk tree for this disk and its children.
669 a8083063 Iustin Pop

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

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

705 6d33a6eb Iustin Pop
    This only works for VG-based disks.
706 6d33a6eb Iustin Pop

707 6d33a6eb Iustin Pop
    @type amount: integer
708 6d33a6eb Iustin Pop
    @param amount: the desired increase in (user-visible) disk space
709 6d33a6eb Iustin Pop
    @rtype: dict
710 6d33a6eb Iustin Pop
    @return: a dictionary of volume-groups and the required size
711 6d33a6eb Iustin Pop

712 6d33a6eb Iustin Pop
    """
713 6d33a6eb Iustin Pop
    if self.dev_type == constants.LD_LV:
714 6d33a6eb Iustin Pop
      return {self.logical_id[0]: amount}
715 6d33a6eb Iustin Pop
    elif self.dev_type == constants.LD_DRBD8:
716 6d33a6eb Iustin Pop
      if self.children:
717 6d33a6eb Iustin Pop
        return self.children[0].ComputeGrowth(amount)
718 6d33a6eb Iustin Pop
      else:
719 6d33a6eb Iustin Pop
        return {}
720 6d33a6eb Iustin Pop
    else:
721 6d33a6eb Iustin Pop
      # Other disk types do not require VG space
722 6d33a6eb Iustin Pop
      return {}
723 6d33a6eb Iustin Pop
724 acec9d51 Iustin Pop
  def RecordGrow(self, amount):
725 acec9d51 Iustin Pop
    """Update the size of this disk after growth.
726 acec9d51 Iustin Pop

727 acec9d51 Iustin Pop
    This method recurses over the disks's children and updates their
728 acec9d51 Iustin Pop
    size correspondigly. The method needs to be kept in sync with the
729 acec9d51 Iustin Pop
    actual algorithms from bdev.
730 acec9d51 Iustin Pop

731 acec9d51 Iustin Pop
    """
732 7181fba0 Constantinos Venetsanopoulos
    if self.dev_type in (constants.LD_LV, constants.LD_FILE,
733 7181fba0 Constantinos Venetsanopoulos
                         constants.LD_RBD):
734 acec9d51 Iustin Pop
      self.size += amount
735 acec9d51 Iustin Pop
    elif self.dev_type == constants.LD_DRBD8:
736 acec9d51 Iustin Pop
      if self.children:
737 acec9d51 Iustin Pop
        self.children[0].RecordGrow(amount)
738 acec9d51 Iustin Pop
      self.size += amount
739 acec9d51 Iustin Pop
    else:
740 acec9d51 Iustin Pop
      raise errors.ProgrammerError("Disk.RecordGrow called for unsupported"
741 acec9d51 Iustin Pop
                                   " disk type %s" % self.dev_type)
742 acec9d51 Iustin Pop
743 735e1318 Michael Hanselmann
  def Update(self, size=None, mode=None):
744 735e1318 Michael Hanselmann
    """Apply changes to size and mode.
745 735e1318 Michael Hanselmann

746 735e1318 Michael Hanselmann
    """
747 735e1318 Michael Hanselmann
    if self.dev_type == constants.LD_DRBD8:
748 735e1318 Michael Hanselmann
      if self.children:
749 735e1318 Michael Hanselmann
        self.children[0].Update(size=size, mode=mode)
750 735e1318 Michael Hanselmann
    else:
751 735e1318 Michael Hanselmann
      assert not self.children
752 735e1318 Michael Hanselmann
753 735e1318 Michael Hanselmann
    if size is not None:
754 735e1318 Michael Hanselmann
      self.size = size
755 735e1318 Michael Hanselmann
    if mode is not None:
756 735e1318 Michael Hanselmann
      self.mode = mode
757 735e1318 Michael Hanselmann
758 a805ec18 Iustin Pop
  def UnsetSize(self):
759 a805ec18 Iustin Pop
    """Sets recursively the size to zero for the disk and its children.
760 a805ec18 Iustin Pop

761 a805ec18 Iustin Pop
    """
762 a805ec18 Iustin Pop
    if self.children:
763 a805ec18 Iustin Pop
      for child in self.children:
764 a805ec18 Iustin Pop
        child.UnsetSize()
765 a805ec18 Iustin Pop
    self.size = 0
766 a805ec18 Iustin Pop
767 0402302c Iustin Pop
  def SetPhysicalID(self, target_node, nodes_ip):
768 0402302c Iustin Pop
    """Convert the logical ID to the physical ID.
769 0402302c Iustin Pop

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

772 0402302c Iustin Pop
    The routine descends down and updates its children also, because
773 0402302c Iustin Pop
    this helps when the only the top device is passed to the remote
774 0402302c Iustin Pop
    node.
775 0402302c Iustin Pop

776 0402302c Iustin Pop
    Arguments:
777 0402302c Iustin Pop
      - target_node: the node we wish to configure for
778 0402302c Iustin Pop
      - nodes_ip: a mapping of node name to ip
779 0402302c Iustin Pop

780 0402302c Iustin Pop
    The target_node must exist in in nodes_ip, and must be one of the
781 0402302c Iustin Pop
    nodes in the logical ID for each of the DRBD devices encountered
782 0402302c Iustin Pop
    in the disk tree.
783 0402302c Iustin Pop

784 0402302c Iustin Pop
    """
785 0402302c Iustin Pop
    if self.children:
786 0402302c Iustin Pop
      for child in self.children:
787 0402302c Iustin Pop
        child.SetPhysicalID(target_node, nodes_ip)
788 0402302c Iustin Pop
789 0402302c Iustin Pop
    if self.logical_id is None and self.physical_id is not None:
790 0402302c Iustin Pop
      return
791 0402302c Iustin Pop
    if self.dev_type in constants.LDS_DRBD:
792 f9518d38 Iustin Pop
      pnode, snode, port, pminor, sminor, secret = self.logical_id
793 0402302c Iustin Pop
      if target_node not in (pnode, snode):
794 0402302c Iustin Pop
        raise errors.ConfigurationError("DRBD device not knowing node %s" %
795 0402302c Iustin Pop
                                        target_node)
796 0402302c Iustin Pop
      pnode_ip = nodes_ip.get(pnode, None)
797 0402302c Iustin Pop
      snode_ip = nodes_ip.get(snode, None)
798 0402302c Iustin Pop
      if pnode_ip is None or snode_ip is None:
799 0402302c Iustin Pop
        raise errors.ConfigurationError("Can't find primary or secondary node"
800 0402302c Iustin Pop
                                        " for %s" % str(self))
801 ffa1c0dc Iustin Pop
      p_data = (pnode_ip, port)
802 ffa1c0dc Iustin Pop
      s_data = (snode_ip, port)
803 0402302c Iustin Pop
      if pnode == target_node:
804 f9518d38 Iustin Pop
        self.physical_id = p_data + s_data + (pminor, secret)
805 0402302c Iustin Pop
      else: # it must be secondary, we tested above
806 f9518d38 Iustin Pop
        self.physical_id = s_data + p_data + (sminor, secret)
807 0402302c Iustin Pop
    else:
808 0402302c Iustin Pop
      self.physical_id = self.logical_id
809 0402302c Iustin Pop
    return
810 0402302c Iustin Pop
811 ff9c047c Iustin Pop
  def ToDict(self):
812 ff9c047c Iustin Pop
    """Disk-specific conversion to standard python types.
813 ff9c047c Iustin Pop

814 ff9c047c Iustin Pop
    This replaces the children lists of objects with lists of
815 ff9c047c Iustin Pop
    standard python types.
816 ff9c047c Iustin Pop

817 ff9c047c Iustin Pop
    """
818 ff9c047c Iustin Pop
    bo = super(Disk, self).ToDict()
819 ff9c047c Iustin Pop
820 ff9c047c Iustin Pop
    for attr in ("children",):
821 ff9c047c Iustin Pop
      alist = bo.get(attr, None)
822 ff9c047c Iustin Pop
      if alist:
823 ff9c047c Iustin Pop
        bo[attr] = self._ContainerToDicts(alist)
824 ff9c047c Iustin Pop
    return bo
825 ff9c047c Iustin Pop
826 ff9c047c Iustin Pop
  @classmethod
827 ff9c047c Iustin Pop
  def FromDict(cls, val):
828 ff9c047c Iustin Pop
    """Custom function for Disks
829 ff9c047c Iustin Pop

830 ff9c047c Iustin Pop
    """
831 ff9c047c Iustin Pop
    obj = super(Disk, cls).FromDict(val)
832 ff9c047c Iustin Pop
    if obj.children:
833 ff9c047c Iustin Pop
      obj.children = cls._ContainerFromDicts(obj.children, list, Disk)
834 ff9c047c Iustin Pop
    if obj.logical_id and isinstance(obj.logical_id, list):
835 ff9c047c Iustin Pop
      obj.logical_id = tuple(obj.logical_id)
836 ff9c047c Iustin Pop
    if obj.physical_id and isinstance(obj.physical_id, list):
837 ff9c047c Iustin Pop
      obj.physical_id = tuple(obj.physical_id)
838 f9518d38 Iustin Pop
    if obj.dev_type in constants.LDS_DRBD:
839 f9518d38 Iustin Pop
      # we need a tuple of length six here
840 f9518d38 Iustin Pop
      if len(obj.logical_id) < 6:
841 f9518d38 Iustin Pop
        obj.logical_id += (None,) * (6 - len(obj.logical_id))
842 ff9c047c Iustin Pop
    return obj
843 ff9c047c Iustin Pop
844 65a15336 Iustin Pop
  def __str__(self):
845 65a15336 Iustin Pop
    """Custom str() formatter for disks.
846 65a15336 Iustin Pop

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

882 332d0e37 Iustin Pop
    """
883 7c4d6c7b Michael Hanselmann
    all_errors = []
884 332d0e37 Iustin Pop
    if self.mode not in constants.DISK_ACCESS_SET:
885 7c4d6c7b Michael Hanselmann
      all_errors.append("Disk access mode '%s' is invalid" % (self.mode, ))
886 7c4d6c7b Michael Hanselmann
    return all_errors
887 332d0e37 Iustin Pop
888 90d726a8 Iustin Pop
  def UpgradeConfig(self):
889 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
890 90d726a8 Iustin Pop

891 90d726a8 Iustin Pop
    """
892 90d726a8 Iustin Pop
    if self.children:
893 90d726a8 Iustin Pop
      for child in self.children:
894 90d726a8 Iustin Pop
        child.UpgradeConfig()
895 bc5d0215 Andrea Spadaccini
896 bc5d0215 Andrea Spadaccini
    if not self.params:
897 bc5d0215 Andrea Spadaccini
      self.params = constants.DISK_LD_DEFAULTS[self.dev_type].copy()
898 bc5d0215 Andrea Spadaccini
    else:
899 bc5d0215 Andrea Spadaccini
      self.params = FillDict(constants.DISK_LD_DEFAULTS[self.dev_type],
900 bc5d0215 Andrea Spadaccini
                             self.params)
901 90d726a8 Iustin Pop
    # add here config upgrade for this disk
902 90d726a8 Iustin Pop
903 a8083063 Iustin Pop
904 918eb80b Agata Murawska
class InstancePolicy(ConfigObject):
905 ffa339ca Iustin Pop
  """Config object representing instance policy limits dictionary.
906 918eb80b Agata Murawska

907 ffa339ca Iustin Pop

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

911 ffa339ca Iustin Pop
  """
912 918eb80b Agata Murawska
  @classmethod
913 918eb80b Agata Murawska
  def CheckParameterSyntax(cls, ipolicy):
914 918eb80b Agata Murawska
    """ Check the instance policy for validity.
915 918eb80b Agata Murawska

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

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

936 918eb80b Agata Murawska
    @type ipolicy: dict
937 918eb80b Agata Murawska
    @param ipolicy: dictionary with min, max, std specs
938 918eb80b Agata Murawska
    @type name: string
939 918eb80b Agata Murawska
    @param name: what are the limits for
940 918eb80b Agata Murawska
    @raise errors.ConfigureError: when specs for given name are not valid
941 918eb80b Agata Murawska

942 918eb80b Agata Murawska
    """
943 4f725341 Agata Murawska
    min_v = ipolicy[constants.ISPECS_MIN].get(name, 0)
944 4f725341 Agata Murawska
    std_v = ipolicy[constants.ISPECS_STD].get(name, min_v)
945 4f725341 Agata Murawska
    max_v = ipolicy[constants.ISPECS_MAX].get(name, std_v)
946 918eb80b Agata Murawska
    err = ("Invalid specification of min/max/std values for %s: %s/%s/%s" %
947 918eb80b Agata Murawska
           (name,
948 4f725341 Agata Murawska
            ipolicy[constants.ISPECS_MIN].get(name, "-"),
949 4f725341 Agata Murawska
            ipolicy[constants.ISPECS_MAX].get(name, "-"),
950 4f725341 Agata Murawska
            ipolicy[constants.ISPECS_STD].get(name, "-")))
951 918eb80b Agata Murawska
    if min_v > std_v or std_v > max_v:
952 918eb80b Agata Murawska
      raise errors.ConfigurationError(err)
953 918eb80b Agata Murawska
954 2cc673a3 Iustin Pop
  @classmethod
955 2cc673a3 Iustin Pop
  def CheckDiskTemplates(cls, disk_templates):
956 2cc673a3 Iustin Pop
    """Checks the disk templates for validity.
957 2cc673a3 Iustin Pop

958 2cc673a3 Iustin Pop
    """
959 2cc673a3 Iustin Pop
    wrong = frozenset(disk_templates).difference(constants.DISK_TEMPLATES)
960 2cc673a3 Iustin Pop
    if wrong:
961 2cc673a3 Iustin Pop
      raise errors.ConfigurationError("Invalid disk template(s) %s" %
962 2cc673a3 Iustin Pop
                                      utils.CommaJoin(wrong))
963 2cc673a3 Iustin Pop
964 ff6c5e55 Iustin Pop
  @classmethod
965 ff6c5e55 Iustin Pop
  def CheckParameter(cls, key, value):
966 ff6c5e55 Iustin Pop
    """Checks a parameter.
967 ff6c5e55 Iustin Pop

968 ff6c5e55 Iustin Pop
    Currently we expect all parameters to be float values.
969 ff6c5e55 Iustin Pop

970 ff6c5e55 Iustin Pop
    """
971 ff6c5e55 Iustin Pop
    try:
972 ff6c5e55 Iustin Pop
      float(value)
973 ff6c5e55 Iustin Pop
    except (TypeError, ValueError), err:
974 ff6c5e55 Iustin Pop
      raise errors.ConfigurationError("Invalid value for key" " '%s':"
975 ff6c5e55 Iustin Pop
                                      " '%s', error: %s" % (key, value, err))
976 ff6c5e55 Iustin Pop
977 918eb80b Agata Murawska
978 ec29fe40 Iustin Pop
class Instance(TaggableObject):
979 a8083063 Iustin Pop
  """Config object representing an instance."""
980 154b9580 Balazs Lecz
  __slots__ = [
981 a8083063 Iustin Pop
    "name",
982 a8083063 Iustin Pop
    "primary_node",
983 a8083063 Iustin Pop
    "os",
984 e69d05fd Iustin Pop
    "hypervisor",
985 5bf7b5cf Iustin Pop
    "hvparams",
986 5bf7b5cf Iustin Pop
    "beparams",
987 1bdcbbab Iustin Pop
    "osparams",
988 9ca8a7c5 Agata Murawska
    "admin_state",
989 a8083063 Iustin Pop
    "nics",
990 a8083063 Iustin Pop
    "disks",
991 a8083063 Iustin Pop
    "disk_template",
992 58acb49d Alexander Schreiber
    "network_port",
993 be1fa613 Iustin Pop
    "serial_no",
994 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
995 a8083063 Iustin Pop
996 a8083063 Iustin Pop
  def _ComputeSecondaryNodes(self):
997 a8083063 Iustin Pop
    """Compute the list of secondary nodes.
998 a8083063 Iustin Pop

999 cfcc5c6d Iustin Pop
    This is a simple wrapper over _ComputeAllNodes.
1000 cfcc5c6d Iustin Pop

1001 cfcc5c6d Iustin Pop
    """
1002 cfcc5c6d Iustin Pop
    all_nodes = set(self._ComputeAllNodes())
1003 cfcc5c6d Iustin Pop
    all_nodes.discard(self.primary_node)
1004 cfcc5c6d Iustin Pop
    return tuple(all_nodes)
1005 cfcc5c6d Iustin Pop
1006 cfcc5c6d Iustin Pop
  secondary_nodes = property(_ComputeSecondaryNodes, None, None,
1007 cfcc5c6d Iustin Pop
                             "List of secondary nodes")
1008 cfcc5c6d Iustin Pop
1009 cfcc5c6d Iustin Pop
  def _ComputeAllNodes(self):
1010 cfcc5c6d Iustin Pop
    """Compute the list of all nodes.
1011 cfcc5c6d Iustin Pop

1012 a8083063 Iustin Pop
    Since the data is already there (in the drbd disks), keeping it as
1013 a8083063 Iustin Pop
    a separate normal attribute is redundant and if not properly
1014 a8083063 Iustin Pop
    synchronised can cause problems. Thus it's better to compute it
1015 a8083063 Iustin Pop
    dynamically.
1016 a8083063 Iustin Pop

1017 a8083063 Iustin Pop
    """
1018 cfcc5c6d Iustin Pop
    def _Helper(nodes, device):
1019 cfcc5c6d Iustin Pop
      """Recursively computes nodes given a top device."""
1020 a1f445d3 Iustin Pop
      if device.dev_type in constants.LDS_DRBD:
1021 cfcc5c6d Iustin Pop
        nodea, nodeb = device.logical_id[:2]
1022 cfcc5c6d Iustin Pop
        nodes.add(nodea)
1023 cfcc5c6d Iustin Pop
        nodes.add(nodeb)
1024 a8083063 Iustin Pop
      if device.children:
1025 a8083063 Iustin Pop
        for child in device.children:
1026 cfcc5c6d Iustin Pop
          _Helper(nodes, child)
1027 a8083063 Iustin Pop
1028 cfcc5c6d Iustin Pop
    all_nodes = set()
1029 99c7b2a1 Iustin Pop
    all_nodes.add(self.primary_node)
1030 a8083063 Iustin Pop
    for device in self.disks:
1031 cfcc5c6d Iustin Pop
      _Helper(all_nodes, device)
1032 cfcc5c6d Iustin Pop
    return tuple(all_nodes)
1033 a8083063 Iustin Pop
1034 cfcc5c6d Iustin Pop
  all_nodes = property(_ComputeAllNodes, None, None,
1035 cfcc5c6d Iustin Pop
                       "List of all nodes of the instance")
1036 a8083063 Iustin Pop
1037 a8083063 Iustin Pop
  def MapLVsByNode(self, lvmap=None, devs=None, node=None):
1038 a8083063 Iustin Pop
    """Provide a mapping of nodes to LVs this instance owns.
1039 a8083063 Iustin Pop

1040 c41eea6e Iustin Pop
    This function figures out what logical volumes should belong on
1041 c41eea6e Iustin Pop
    which nodes, recursing through a device tree.
1042 a8083063 Iustin Pop

1043 c41eea6e Iustin Pop
    @param lvmap: optional dictionary to receive the
1044 c41eea6e Iustin Pop
        'node' : ['lv', ...] data.
1045 a8083063 Iustin Pop

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

1051 a8083063 Iustin Pop
    """
1052 a8083063 Iustin Pop
    if node == None:
1053 a8083063 Iustin Pop
      node = self.primary_node
1054 a8083063 Iustin Pop
1055 a8083063 Iustin Pop
    if lvmap is None:
1056 e687ec01 Michael Hanselmann
      lvmap = {
1057 e687ec01 Michael Hanselmann
        node: [],
1058 e687ec01 Michael Hanselmann
        }
1059 a8083063 Iustin Pop
      ret = lvmap
1060 a8083063 Iustin Pop
    else:
1061 a8083063 Iustin Pop
      if not node in lvmap:
1062 a8083063 Iustin Pop
        lvmap[node] = []
1063 a8083063 Iustin Pop
      ret = None
1064 a8083063 Iustin Pop
1065 a8083063 Iustin Pop
    if not devs:
1066 a8083063 Iustin Pop
      devs = self.disks
1067 a8083063 Iustin Pop
1068 a8083063 Iustin Pop
    for dev in devs:
1069 fe96220b Iustin Pop
      if dev.dev_type == constants.LD_LV:
1070 e687ec01 Michael Hanselmann
        lvmap[node].append(dev.logical_id[0] + "/" + dev.logical_id[1])
1071 a8083063 Iustin Pop
1072 a1f445d3 Iustin Pop
      elif dev.dev_type in constants.LDS_DRBD:
1073 a8083063 Iustin Pop
        if dev.children:
1074 a8083063 Iustin Pop
          self.MapLVsByNode(lvmap, dev.children, dev.logical_id[0])
1075 a8083063 Iustin Pop
          self.MapLVsByNode(lvmap, dev.children, dev.logical_id[1])
1076 a8083063 Iustin Pop
1077 a8083063 Iustin Pop
      elif dev.children:
1078 a8083063 Iustin Pop
        self.MapLVsByNode(lvmap, dev.children, node)
1079 a8083063 Iustin Pop
1080 a8083063 Iustin Pop
    return ret
1081 a8083063 Iustin Pop
1082 ad24e046 Iustin Pop
  def FindDisk(self, idx):
1083 ad24e046 Iustin Pop
    """Find a disk given having a specified index.
1084 644eeef9 Iustin Pop

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

1087 ad24e046 Iustin Pop
    @type idx: int
1088 ad24e046 Iustin Pop
    @param idx: the disk index
1089 ad24e046 Iustin Pop
    @rtype: L{Disk}
1090 ad24e046 Iustin Pop
    @return: the corresponding disk
1091 ad24e046 Iustin Pop
    @raise errors.OpPrereqError: when the given index is not valid
1092 644eeef9 Iustin Pop

1093 ad24e046 Iustin Pop
    """
1094 ad24e046 Iustin Pop
    try:
1095 ad24e046 Iustin Pop
      idx = int(idx)
1096 ad24e046 Iustin Pop
      return self.disks[idx]
1097 691744c4 Iustin Pop
    except (TypeError, ValueError), err:
1098 debac808 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index: '%s'" % str(err),
1099 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
1100 ad24e046 Iustin Pop
    except IndexError:
1101 ad24e046 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index: %d (instace has disks"
1102 daa55b04 Michael Hanselmann
                                 " 0 to %d" % (idx, len(self.disks) - 1),
1103 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
1104 644eeef9 Iustin Pop
1105 ff9c047c Iustin Pop
  def ToDict(self):
1106 ff9c047c Iustin Pop
    """Instance-specific conversion to standard python types.
1107 ff9c047c Iustin Pop

1108 ff9c047c Iustin Pop
    This replaces the children lists of objects with lists of standard
1109 ff9c047c Iustin Pop
    python types.
1110 ff9c047c Iustin Pop

1111 ff9c047c Iustin Pop
    """
1112 ff9c047c Iustin Pop
    bo = super(Instance, self).ToDict()
1113 ff9c047c Iustin Pop
1114 ff9c047c Iustin Pop
    for attr in "nics", "disks":
1115 ff9c047c Iustin Pop
      alist = bo.get(attr, None)
1116 ff9c047c Iustin Pop
      if alist:
1117 ff9c047c Iustin Pop
        nlist = self._ContainerToDicts(alist)
1118 ff9c047c Iustin Pop
      else:
1119 ff9c047c Iustin Pop
        nlist = []
1120 ff9c047c Iustin Pop
      bo[attr] = nlist
1121 ff9c047c Iustin Pop
    return bo
1122 ff9c047c Iustin Pop
1123 ff9c047c Iustin Pop
  @classmethod
1124 ff9c047c Iustin Pop
  def FromDict(cls, val):
1125 ff9c047c Iustin Pop
    """Custom function for instances.
1126 ff9c047c Iustin Pop

1127 ff9c047c Iustin Pop
    """
1128 9ca8a7c5 Agata Murawska
    if "admin_state" not in val:
1129 9ca8a7c5 Agata Murawska
      if val.get("admin_up", False):
1130 9ca8a7c5 Agata Murawska
        val["admin_state"] = constants.ADMINST_UP
1131 9ca8a7c5 Agata Murawska
      else:
1132 9ca8a7c5 Agata Murawska
        val["admin_state"] = constants.ADMINST_DOWN
1133 9ca8a7c5 Agata Murawska
    if "admin_up" in val:
1134 9ca8a7c5 Agata Murawska
      del val["admin_up"]
1135 ff9c047c Iustin Pop
    obj = super(Instance, cls).FromDict(val)
1136 ff9c047c Iustin Pop
    obj.nics = cls._ContainerFromDicts(obj.nics, list, NIC)
1137 ff9c047c Iustin Pop
    obj.disks = cls._ContainerFromDicts(obj.disks, list, Disk)
1138 ff9c047c Iustin Pop
    return obj
1139 ff9c047c Iustin Pop
1140 90d726a8 Iustin Pop
  def UpgradeConfig(self):
1141 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
1142 90d726a8 Iustin Pop

1143 90d726a8 Iustin Pop
    """
1144 90d726a8 Iustin Pop
    for nic in self.nics:
1145 90d726a8 Iustin Pop
      nic.UpgradeConfig()
1146 90d726a8 Iustin Pop
    for disk in self.disks:
1147 90d726a8 Iustin Pop
      disk.UpgradeConfig()
1148 7736a5f2 Iustin Pop
    if self.hvparams:
1149 7736a5f2 Iustin Pop
      for key in constants.HVC_GLOBALS:
1150 7736a5f2 Iustin Pop
        try:
1151 7736a5f2 Iustin Pop
          del self.hvparams[key]
1152 7736a5f2 Iustin Pop
        except KeyError:
1153 7736a5f2 Iustin Pop
          pass
1154 1bdcbbab Iustin Pop
    if self.osparams is None:
1155 1bdcbbab Iustin Pop
      self.osparams = {}
1156 8c72ab2b Guido Trotter
    UpgradeBeParams(self.beparams)
1157 90d726a8 Iustin Pop
1158 a8083063 Iustin Pop
1159 a8083063 Iustin Pop
class OS(ConfigObject):
1160 b41b3516 Iustin Pop
  """Config object representing an operating system.
1161 b41b3516 Iustin Pop

1162 b41b3516 Iustin Pop
  @type supported_parameters: list
1163 b41b3516 Iustin Pop
  @ivar supported_parameters: a list of tuples, name and description,
1164 b41b3516 Iustin Pop
      containing the supported parameters by this OS
1165 b41b3516 Iustin Pop

1166 870dc44c Iustin Pop
  @type VARIANT_DELIM: string
1167 870dc44c Iustin Pop
  @cvar VARIANT_DELIM: the variant delimiter
1168 870dc44c Iustin Pop

1169 b41b3516 Iustin Pop
  """
1170 a8083063 Iustin Pop
  __slots__ = [
1171 a8083063 Iustin Pop
    "name",
1172 a8083063 Iustin Pop
    "path",
1173 082a7f91 Guido Trotter
    "api_versions",
1174 a8083063 Iustin Pop
    "create_script",
1175 a8083063 Iustin Pop
    "export_script",
1176 386b57af Iustin Pop
    "import_script",
1177 386b57af Iustin Pop
    "rename_script",
1178 b41b3516 Iustin Pop
    "verify_script",
1179 6d79896b Guido Trotter
    "supported_variants",
1180 b41b3516 Iustin Pop
    "supported_parameters",
1181 a8083063 Iustin Pop
    ]
1182 a8083063 Iustin Pop
1183 870dc44c Iustin Pop
  VARIANT_DELIM = "+"
1184 870dc44c Iustin Pop
1185 870dc44c Iustin Pop
  @classmethod
1186 870dc44c Iustin Pop
  def SplitNameVariant(cls, name):
1187 870dc44c Iustin Pop
    """Splits the name into the proper name and variant.
1188 870dc44c Iustin Pop

1189 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
1190 870dc44c Iustin Pop
    @rtype: list
1191 870dc44c Iustin Pop
    @return: a list of two elements; if the original name didn't
1192 870dc44c Iustin Pop
        contain a variant, it's returned as an empty string
1193 870dc44c Iustin Pop

1194 870dc44c Iustin Pop
    """
1195 870dc44c Iustin Pop
    nv = name.split(cls.VARIANT_DELIM, 1)
1196 870dc44c Iustin Pop
    if len(nv) == 1:
1197 870dc44c Iustin Pop
      nv.append("")
1198 870dc44c Iustin Pop
    return nv
1199 870dc44c Iustin Pop
1200 870dc44c Iustin Pop
  @classmethod
1201 870dc44c Iustin Pop
  def GetName(cls, name):
1202 870dc44c Iustin Pop
    """Returns the proper name of the os (without the variant).
1203 870dc44c Iustin Pop

1204 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
1205 870dc44c Iustin Pop

1206 870dc44c Iustin Pop
    """
1207 870dc44c Iustin Pop
    return cls.SplitNameVariant(name)[0]
1208 870dc44c Iustin Pop
1209 870dc44c Iustin Pop
  @classmethod
1210 870dc44c Iustin Pop
  def GetVariant(cls, name):
1211 870dc44c Iustin Pop
    """Returns the variant the os (without the base name).
1212 870dc44c Iustin Pop

1213 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
1214 870dc44c Iustin Pop

1215 870dc44c Iustin Pop
    """
1216 870dc44c Iustin Pop
    return cls.SplitNameVariant(name)[1]
1217 870dc44c Iustin Pop
1218 7c0d6283 Michael Hanselmann
1219 5f06ce5e Michael Hanselmann
class NodeHvState(ConfigObject):
1220 5f06ce5e Michael Hanselmann
  """Hypvervisor state on a node.
1221 5f06ce5e Michael Hanselmann

1222 5f06ce5e Michael Hanselmann
  @ivar mem_total: Total amount of memory
1223 5f06ce5e Michael Hanselmann
  @ivar mem_node: Memory used by, or reserved for, the node itself (not always
1224 5f06ce5e Michael Hanselmann
    available)
1225 5f06ce5e Michael Hanselmann
  @ivar mem_hv: Memory used by hypervisor or lost due to instance allocation
1226 5f06ce5e Michael Hanselmann
    rounding
1227 5f06ce5e Michael Hanselmann
  @ivar mem_inst: Memory used by instances living on node
1228 5f06ce5e Michael Hanselmann
  @ivar cpu_total: Total node CPU core count
1229 5f06ce5e Michael Hanselmann
  @ivar cpu_node: Number of CPU cores reserved for the node itself
1230 5f06ce5e Michael Hanselmann

1231 5f06ce5e Michael Hanselmann
  """
1232 5f06ce5e Michael Hanselmann
  __slots__ = [
1233 5f06ce5e Michael Hanselmann
    "mem_total",
1234 5f06ce5e Michael Hanselmann
    "mem_node",
1235 5f06ce5e Michael Hanselmann
    "mem_hv",
1236 5f06ce5e Michael Hanselmann
    "mem_inst",
1237 5f06ce5e Michael Hanselmann
    "cpu_total",
1238 5f06ce5e Michael Hanselmann
    "cpu_node",
1239 5f06ce5e Michael Hanselmann
    ] + _TIMESTAMPS
1240 5f06ce5e Michael Hanselmann
1241 5f06ce5e Michael Hanselmann
1242 5f06ce5e Michael Hanselmann
class NodeDiskState(ConfigObject):
1243 5f06ce5e Michael Hanselmann
  """Disk state on a node.
1244 5f06ce5e Michael Hanselmann

1245 5f06ce5e Michael Hanselmann
  """
1246 5f06ce5e Michael Hanselmann
  __slots__ = [
1247 5f06ce5e Michael Hanselmann
    "total",
1248 5f06ce5e Michael Hanselmann
    "reserved",
1249 5f06ce5e Michael Hanselmann
    "overhead",
1250 5f06ce5e Michael Hanselmann
    ] + _TIMESTAMPS
1251 5f06ce5e Michael Hanselmann
1252 5f06ce5e Michael Hanselmann
1253 ec29fe40 Iustin Pop
class Node(TaggableObject):
1254 634d30f4 Michael Hanselmann
  """Config object representing a node.
1255 634d30f4 Michael Hanselmann

1256 634d30f4 Michael Hanselmann
  @ivar hv_state: Hypervisor state (e.g. number of CPUs)
1257 634d30f4 Michael Hanselmann
  @ivar hv_state_static: Hypervisor state overriden by user
1258 634d30f4 Michael Hanselmann
  @ivar disk_state: Disk state (e.g. free space)
1259 634d30f4 Michael Hanselmann
  @ivar disk_state_static: Disk state overriden by user
1260 634d30f4 Michael Hanselmann

1261 634d30f4 Michael Hanselmann
  """
1262 154b9580 Balazs Lecz
  __slots__ = [
1263 ec29fe40 Iustin Pop
    "name",
1264 ec29fe40 Iustin Pop
    "primary_ip",
1265 ec29fe40 Iustin Pop
    "secondary_ip",
1266 be1fa613 Iustin Pop
    "serial_no",
1267 8b8b8b81 Iustin Pop
    "master_candidate",
1268 fc0fe88c Iustin Pop
    "offline",
1269 af64c0ea Iustin Pop
    "drained",
1270 f936c153 Iustin Pop
    "group",
1271 490acd18 Iustin Pop
    "master_capable",
1272 490acd18 Iustin Pop
    "vm_capable",
1273 095e71aa René Nussbaumer
    "ndparams",
1274 25124d4a René Nussbaumer
    "powered",
1275 5b49ed09 René Nussbaumer
    "hv_state",
1276 634d30f4 Michael Hanselmann
    "hv_state_static",
1277 5b49ed09 René Nussbaumer
    "disk_state",
1278 634d30f4 Michael Hanselmann
    "disk_state_static",
1279 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
1280 a8083063 Iustin Pop
1281 490acd18 Iustin Pop
  def UpgradeConfig(self):
1282 490acd18 Iustin Pop
    """Fill defaults for missing configuration values.
1283 490acd18 Iustin Pop

1284 490acd18 Iustin Pop
    """
1285 b459a848 Andrea Spadaccini
    # pylint: disable=E0203
1286 490acd18 Iustin Pop
    # because these are "defined" via slots, not manually
1287 490acd18 Iustin Pop
    if self.master_capable is None:
1288 490acd18 Iustin Pop
      self.master_capable = True
1289 490acd18 Iustin Pop
1290 490acd18 Iustin Pop
    if self.vm_capable is None:
1291 490acd18 Iustin Pop
      self.vm_capable = True
1292 490acd18 Iustin Pop
1293 095e71aa René Nussbaumer
    if self.ndparams is None:
1294 095e71aa René Nussbaumer
      self.ndparams = {}
1295 095e71aa René Nussbaumer
1296 25124d4a René Nussbaumer
    if self.powered is None:
1297 25124d4a René Nussbaumer
      self.powered = True
1298 25124d4a René Nussbaumer
1299 5f06ce5e Michael Hanselmann
  def ToDict(self):
1300 5f06ce5e Michael Hanselmann
    """Custom function for serializing.
1301 5f06ce5e Michael Hanselmann

1302 5f06ce5e Michael Hanselmann
    """
1303 5f06ce5e Michael Hanselmann
    data = super(Node, self).ToDict()
1304 5f06ce5e Michael Hanselmann
1305 5f06ce5e Michael Hanselmann
    hv_state = data.get("hv_state", None)
1306 5f06ce5e Michael Hanselmann
    if hv_state is not None:
1307 5f06ce5e Michael Hanselmann
      data["hv_state"] = self._ContainerToDicts(hv_state)
1308 5f06ce5e Michael Hanselmann
1309 5f06ce5e Michael Hanselmann
    disk_state = data.get("disk_state", None)
1310 5f06ce5e Michael Hanselmann
    if disk_state is not None:
1311 5f06ce5e Michael Hanselmann
      data["disk_state"] = \
1312 5f06ce5e Michael Hanselmann
        dict((key, self._ContainerToDicts(value))
1313 5f06ce5e Michael Hanselmann
             for (key, value) in disk_state.items())
1314 5f06ce5e Michael Hanselmann
1315 5f06ce5e Michael Hanselmann
    return data
1316 5f06ce5e Michael Hanselmann
1317 5f06ce5e Michael Hanselmann
  @classmethod
1318 5f06ce5e Michael Hanselmann
  def FromDict(cls, val):
1319 5f06ce5e Michael Hanselmann
    """Custom function for deserializing.
1320 5f06ce5e Michael Hanselmann

1321 5f06ce5e Michael Hanselmann
    """
1322 5f06ce5e Michael Hanselmann
    obj = super(Node, cls).FromDict(val)
1323 5f06ce5e Michael Hanselmann
1324 5f06ce5e Michael Hanselmann
    if obj.hv_state is not None:
1325 5f06ce5e Michael Hanselmann
      obj.hv_state = cls._ContainerFromDicts(obj.hv_state, dict, NodeHvState)
1326 5f06ce5e Michael Hanselmann
1327 5f06ce5e Michael Hanselmann
    if obj.disk_state is not None:
1328 5f06ce5e Michael Hanselmann
      obj.disk_state = \
1329 5f06ce5e Michael Hanselmann
        dict((key, cls._ContainerFromDicts(value, dict, NodeDiskState))
1330 5f06ce5e Michael Hanselmann
             for (key, value) in obj.disk_state.items())
1331 5f06ce5e Michael Hanselmann
1332 5f06ce5e Michael Hanselmann
    return obj
1333 5f06ce5e Michael Hanselmann
1334 a8083063 Iustin Pop
1335 1ffd2673 Michael Hanselmann
class NodeGroup(TaggableObject):
1336 24a3707f Guido Trotter
  """Config object representing a node group."""
1337 24a3707f Guido Trotter
  __slots__ = [
1338 24a3707f Guido Trotter
    "name",
1339 24a3707f Guido Trotter
    "members",
1340 095e71aa René Nussbaumer
    "ndparams",
1341 bc5d0215 Andrea Spadaccini
    "diskparams",
1342 81e3ab4f Agata Murawska
    "ipolicy",
1343 e11a1b77 Adeodato Simo
    "serial_no",
1344 a8282327 René Nussbaumer
    "hv_state_static",
1345 a8282327 René Nussbaumer
    "disk_state_static",
1346 90e99856 Adeodato Simo
    "alloc_policy",
1347 24a3707f Guido Trotter
    ] + _TIMESTAMPS + _UUID
1348 24a3707f Guido Trotter
1349 24a3707f Guido Trotter
  def ToDict(self):
1350 24a3707f Guido Trotter
    """Custom function for nodegroup.
1351 24a3707f Guido Trotter

1352 c60abd62 Guido Trotter
    This discards the members object, which gets recalculated and is only kept
1353 c60abd62 Guido Trotter
    in memory.
1354 24a3707f Guido Trotter

1355 24a3707f Guido Trotter
    """
1356 24a3707f Guido Trotter
    mydict = super(NodeGroup, self).ToDict()
1357 24a3707f Guido Trotter
    del mydict["members"]
1358 24a3707f Guido Trotter
    return mydict
1359 24a3707f Guido Trotter
1360 24a3707f Guido Trotter
  @classmethod
1361 24a3707f Guido Trotter
  def FromDict(cls, val):
1362 24a3707f Guido Trotter
    """Custom function for nodegroup.
1363 24a3707f Guido Trotter

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

1366 24a3707f Guido Trotter
    """
1367 24a3707f Guido Trotter
    obj = super(NodeGroup, cls).FromDict(val)
1368 24a3707f Guido Trotter
    obj.members = []
1369 24a3707f Guido Trotter
    return obj
1370 24a3707f Guido Trotter
1371 095e71aa René Nussbaumer
  def UpgradeConfig(self):
1372 095e71aa René Nussbaumer
    """Fill defaults for missing configuration values.
1373 095e71aa René Nussbaumer

1374 095e71aa René Nussbaumer
    """
1375 095e71aa René Nussbaumer
    if self.ndparams is None:
1376 095e71aa René Nussbaumer
      self.ndparams = {}
1377 095e71aa René Nussbaumer
1378 e11a1b77 Adeodato Simo
    if self.serial_no is None:
1379 e11a1b77 Adeodato Simo
      self.serial_no = 1
1380 e11a1b77 Adeodato Simo
1381 90e99856 Adeodato Simo
    if self.alloc_policy is None:
1382 90e99856 Adeodato Simo
      self.alloc_policy = constants.ALLOC_POLICY_PREFERRED
1383 90e99856 Adeodato Simo
1384 4b97458c Iustin Pop
    # We only update mtime, and not ctime, since we would not be able
1385 4b97458c Iustin Pop
    # to provide a correct value for creation time.
1386 e11a1b77 Adeodato Simo
    if self.mtime is None:
1387 e11a1b77 Adeodato Simo
      self.mtime = time.time()
1388 e11a1b77 Adeodato Simo
1389 bc5d0215 Andrea Spadaccini
    self.diskparams = UpgradeDiskParams(self.diskparams)
1390 81e3ab4f Agata Murawska
    if self.ipolicy is None:
1391 81e3ab4f Agata Murawska
      self.ipolicy = MakeEmptyIPolicy()
1392 bc5d0215 Andrea Spadaccini
1393 095e71aa René Nussbaumer
  def FillND(self, node):
1394 ce523de1 Michael Hanselmann
    """Return filled out ndparams for L{objects.Node}
1395 095e71aa René Nussbaumer

1396 095e71aa René Nussbaumer
    @type node: L{objects.Node}
1397 095e71aa René Nussbaumer
    @param node: A Node object to fill
1398 095e71aa René Nussbaumer
    @return a copy of the node's ndparams with defaults filled
1399 095e71aa René Nussbaumer

1400 095e71aa René Nussbaumer
    """
1401 095e71aa René Nussbaumer
    return self.SimpleFillND(node.ndparams)
1402 095e71aa René Nussbaumer
1403 095e71aa René Nussbaumer
  def SimpleFillND(self, ndparams):
1404 095e71aa René Nussbaumer
    """Fill a given ndparams dict with defaults.
1405 095e71aa René Nussbaumer

1406 095e71aa René Nussbaumer
    @type ndparams: dict
1407 095e71aa René Nussbaumer
    @param ndparams: the dict to fill
1408 095e71aa René Nussbaumer
    @rtype: dict
1409 095e71aa René Nussbaumer
    @return: a copy of the passed in ndparams with missing keys filled
1410 e6e88de6 Adeodato Simo
        from the node group defaults
1411 095e71aa René Nussbaumer

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

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

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

1571 0fbedb7a Michael Hanselmann
    """
1572 0fbedb7a Michael Hanselmann
    return self.enabled_hypervisors[0]
1573 0fbedb7a Michael Hanselmann
1574 319856a9 Michael Hanselmann
  def ToDict(self):
1575 319856a9 Michael Hanselmann
    """Custom function for cluster.
1576 319856a9 Michael Hanselmann

1577 319856a9 Michael Hanselmann
    """
1578 b60ae2ca Iustin Pop
    mydict = super(Cluster, self).ToDict()
1579 319856a9 Michael Hanselmann
    mydict["tcpudp_port_pool"] = list(self.tcpudp_port_pool)
1580 319856a9 Michael Hanselmann
    return mydict
1581 319856a9 Michael Hanselmann
1582 319856a9 Michael Hanselmann
  @classmethod
1583 319856a9 Michael Hanselmann
  def FromDict(cls, val):
1584 319856a9 Michael Hanselmann
    """Custom function for cluster.
1585 319856a9 Michael Hanselmann

1586 319856a9 Michael Hanselmann
    """
1587 b60ae2ca Iustin Pop
    obj = super(Cluster, cls).FromDict(val)
1588 319856a9 Michael Hanselmann
    if not isinstance(obj.tcpudp_port_pool, set):
1589 319856a9 Michael Hanselmann
      obj.tcpudp_port_pool = set(obj.tcpudp_port_pool)
1590 319856a9 Michael Hanselmann
    return obj
1591 319856a9 Michael Hanselmann
1592 d63479b5 Iustin Pop
  def GetHVDefaults(self, hypervisor, os_name=None, skip_keys=None):
1593 d63479b5 Iustin Pop
    """Get the default hypervisor parameters for the cluster.
1594 d63479b5 Iustin Pop

1595 d63479b5 Iustin Pop
    @param hypervisor: the hypervisor name
1596 d63479b5 Iustin Pop
    @param os_name: if specified, we'll also update the defaults for this OS
1597 d63479b5 Iustin Pop
    @param skip_keys: if passed, list of keys not to use
1598 d63479b5 Iustin Pop
    @return: the defaults dict
1599 d63479b5 Iustin Pop

1600 d63479b5 Iustin Pop
    """
1601 d63479b5 Iustin Pop
    if skip_keys is None:
1602 d63479b5 Iustin Pop
      skip_keys = []
1603 d63479b5 Iustin Pop
1604 d63479b5 Iustin Pop
    fill_stack = [self.hvparams.get(hypervisor, {})]
1605 d63479b5 Iustin Pop
    if os_name is not None:
1606 d63479b5 Iustin Pop
      os_hvp = self.os_hvp.get(os_name, {}).get(hypervisor, {})
1607 d63479b5 Iustin Pop
      fill_stack.append(os_hvp)
1608 d63479b5 Iustin Pop
1609 d63479b5 Iustin Pop
    ret_dict = {}
1610 d63479b5 Iustin Pop
    for o_dict in fill_stack:
1611 d63479b5 Iustin Pop
      ret_dict = FillDict(ret_dict, o_dict, skip_keys=skip_keys)
1612 d63479b5 Iustin Pop
1613 d63479b5 Iustin Pop
    return ret_dict
1614 d63479b5 Iustin Pop
1615 73e0328b Iustin Pop
  def SimpleFillHV(self, hv_name, os_name, hvparams, skip_globals=False):
1616 73e0328b Iustin Pop
    """Fill a given hvparams dict with cluster defaults.
1617 73e0328b Iustin Pop

1618 73e0328b Iustin Pop
    @type hv_name: string
1619 73e0328b Iustin Pop
    @param hv_name: the hypervisor to use
1620 73e0328b Iustin Pop
    @type os_name: string
1621 73e0328b Iustin Pop
    @param os_name: the OS to use for overriding the hypervisor defaults
1622 73e0328b Iustin Pop
    @type skip_globals: boolean
1623 73e0328b Iustin Pop
    @param skip_globals: if True, the global hypervisor parameters will
1624 73e0328b Iustin Pop
        not be filled
1625 73e0328b Iustin Pop
    @rtype: dict
1626 73e0328b Iustin Pop
    @return: a copy of the given hvparams with missing keys filled from
1627 73e0328b Iustin Pop
        the cluster defaults
1628 73e0328b Iustin Pop

1629 73e0328b Iustin Pop
    """
1630 73e0328b Iustin Pop
    if skip_globals:
1631 73e0328b Iustin Pop
      skip_keys = constants.HVC_GLOBALS
1632 73e0328b Iustin Pop
    else:
1633 73e0328b Iustin Pop
      skip_keys = []
1634 73e0328b Iustin Pop
1635 73e0328b Iustin Pop
    def_dict = self.GetHVDefaults(hv_name, os_name, skip_keys=skip_keys)
1636 73e0328b Iustin Pop
    return FillDict(def_dict, hvparams, skip_keys=skip_keys)
1637 d63479b5 Iustin Pop
1638 7736a5f2 Iustin Pop
  def FillHV(self, instance, skip_globals=False):
1639 73e0328b Iustin Pop
    """Fill an instance's hvparams dict with cluster defaults.
1640 5bf7b5cf Iustin Pop

1641 a2a24f4c Guido Trotter
    @type instance: L{objects.Instance}
1642 5bf7b5cf Iustin Pop
    @param instance: the instance parameter to fill
1643 7736a5f2 Iustin Pop
    @type skip_globals: boolean
1644 7736a5f2 Iustin Pop
    @param skip_globals: if True, the global hypervisor parameters will
1645 7736a5f2 Iustin Pop
        not be filled
1646 5bf7b5cf Iustin Pop
    @rtype: dict
1647 5bf7b5cf Iustin Pop
    @return: a copy of the instance's hvparams with missing keys filled from
1648 5bf7b5cf Iustin Pop
        the cluster defaults
1649 5bf7b5cf Iustin Pop

1650 5bf7b5cf Iustin Pop
    """
1651 73e0328b Iustin Pop
    return self.SimpleFillHV(instance.hypervisor, instance.os,
1652 73e0328b Iustin Pop
                             instance.hvparams, skip_globals)
1653 17463d22 René Nussbaumer
1654 73e0328b Iustin Pop
  def SimpleFillBE(self, beparams):
1655 73e0328b Iustin Pop
    """Fill a given beparams dict with cluster defaults.
1656 73e0328b Iustin Pop

1657 06596a60 Guido Trotter
    @type beparams: dict
1658 06596a60 Guido Trotter
    @param beparams: the dict to fill
1659 73e0328b Iustin Pop
    @rtype: dict
1660 73e0328b Iustin Pop
    @return: a copy of the passed in beparams with missing keys filled
1661 73e0328b Iustin Pop
        from the cluster defaults
1662 73e0328b Iustin Pop

1663 73e0328b Iustin Pop
    """
1664 73e0328b Iustin Pop
    return FillDict(self.beparams.get(constants.PP_DEFAULT, {}), beparams)
1665 5bf7b5cf Iustin Pop
1666 5bf7b5cf Iustin Pop
  def FillBE(self, instance):
1667 73e0328b Iustin Pop
    """Fill an instance's beparams dict with cluster defaults.
1668 5bf7b5cf Iustin Pop

1669 a2a24f4c Guido Trotter
    @type instance: L{objects.Instance}
1670 5bf7b5cf Iustin Pop
    @param instance: the instance parameter to fill
1671 5bf7b5cf Iustin Pop
    @rtype: dict
1672 5bf7b5cf Iustin Pop
    @return: a copy of the instance's beparams with missing keys filled from
1673 5bf7b5cf Iustin Pop
        the cluster defaults
1674 5bf7b5cf Iustin Pop

1675 5bf7b5cf Iustin Pop
    """
1676 73e0328b Iustin Pop
    return self.SimpleFillBE(instance.beparams)
1677 73e0328b Iustin Pop
1678 73e0328b Iustin Pop
  def SimpleFillNIC(self, nicparams):
1679 73e0328b Iustin Pop
    """Fill a given nicparams dict with cluster defaults.
1680 73e0328b Iustin Pop

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

1687 73e0328b Iustin Pop
    """
1688 73e0328b Iustin Pop
    return FillDict(self.nicparams.get(constants.PP_DEFAULT, {}), nicparams)
1689 5bf7b5cf Iustin Pop
1690 1bdcbbab Iustin Pop
  def SimpleFillOS(self, os_name, os_params):
1691 1bdcbbab Iustin Pop
    """Fill an instance's osparams dict with cluster defaults.
1692 1bdcbbab Iustin Pop

1693 1bdcbbab Iustin Pop
    @type os_name: string
1694 1bdcbbab Iustin Pop
    @param os_name: the OS name to use
1695 1bdcbbab Iustin Pop
    @type os_params: dict
1696 1bdcbbab Iustin Pop
    @param os_params: the dict to fill with default values
1697 1bdcbbab Iustin Pop
    @rtype: dict
1698 1bdcbbab Iustin Pop
    @return: a copy of the instance's osparams with missing keys filled from
1699 1bdcbbab Iustin Pop
        the cluster defaults
1700 1bdcbbab Iustin Pop

1701 1bdcbbab Iustin Pop
    """
1702 1bdcbbab Iustin Pop
    name_only = os_name.split("+", 1)[0]
1703 1bdcbbab Iustin Pop
    # base OS
1704 1bdcbbab Iustin Pop
    result = self.osparams.get(name_only, {})
1705 1bdcbbab Iustin Pop
    # OS with variant
1706 1bdcbbab Iustin Pop
    result = FillDict(result, self.osparams.get(os_name, {}))
1707 1bdcbbab Iustin Pop
    # specified params
1708 1bdcbbab Iustin Pop
    return FillDict(result, os_params)
1709 1bdcbbab Iustin Pop
1710 2da9f556 René Nussbaumer
  @staticmethod
1711 2da9f556 René Nussbaumer
  def SimpleFillHvState(hv_state):
1712 2da9f556 René Nussbaumer
    """Fill an hv_state sub dict with cluster defaults.
1713 2da9f556 René Nussbaumer

1714 2da9f556 René Nussbaumer
    """
1715 2da9f556 René Nussbaumer
    return FillDict(constants.HVST_DEFAULTS, hv_state)
1716 2da9f556 René Nussbaumer
1717 2da9f556 René Nussbaumer
  @staticmethod
1718 2da9f556 René Nussbaumer
  def SimpleFillDiskState(disk_state):
1719 2da9f556 René Nussbaumer
    """Fill an disk_state sub dict with cluster defaults.
1720 2da9f556 René Nussbaumer

1721 2da9f556 René Nussbaumer
    """
1722 2da9f556 René Nussbaumer
    return FillDict(constants.DS_DEFAULTS, disk_state)
1723 2da9f556 René Nussbaumer
1724 095e71aa René Nussbaumer
  def FillND(self, node, nodegroup):
1725 ce523de1 Michael Hanselmann
    """Return filled out ndparams for L{objects.NodeGroup} and L{objects.Node}
1726 095e71aa René Nussbaumer

1727 095e71aa René Nussbaumer
    @type node: L{objects.Node}
1728 095e71aa René Nussbaumer
    @param node: A Node object to fill
1729 095e71aa René Nussbaumer
    @type nodegroup: L{objects.NodeGroup}
1730 095e71aa René Nussbaumer
    @param nodegroup: A Node object to fill
1731 095e71aa René Nussbaumer
    @return a copy of the node's ndparams with defaults filled
1732 095e71aa René Nussbaumer

1733 095e71aa René Nussbaumer
    """
1734 095e71aa René Nussbaumer
    return self.SimpleFillND(nodegroup.FillND(node))
1735 095e71aa René Nussbaumer
1736 095e71aa René Nussbaumer
  def SimpleFillND(self, ndparams):
1737 095e71aa René Nussbaumer
    """Fill a given ndparams dict with defaults.
1738 095e71aa René Nussbaumer

1739 095e71aa René Nussbaumer
    @type ndparams: dict
1740 095e71aa René Nussbaumer
    @param ndparams: the dict to fill
1741 095e71aa René Nussbaumer
    @rtype: dict
1742 095e71aa René Nussbaumer
    @return: a copy of the passed in ndparams with missing keys filled
1743 095e71aa René Nussbaumer
        from the cluster defaults
1744 095e71aa René Nussbaumer

1745 095e71aa René Nussbaumer
    """
1746 095e71aa René Nussbaumer
    return FillDict(self.ndparams, ndparams)
1747 095e71aa René Nussbaumer
1748 918eb80b Agata Murawska
  def SimpleFillIPolicy(self, ipolicy):
1749 918eb80b Agata Murawska
    """ Fill instance policy dict with defaults.
1750 918eb80b Agata Murawska

1751 918eb80b Agata Murawska
    @type ipolicy: dict
1752 918eb80b Agata Murawska
    @param ipolicy: the dict to fill
1753 918eb80b Agata Murawska
    @rtype: dict
1754 918eb80b Agata Murawska
    @return: a copy of passed ipolicy with missing keys filled from
1755 918eb80b Agata Murawska
      the cluster defaults
1756 918eb80b Agata Murawska

1757 918eb80b Agata Murawska
    """
1758 2cc673a3 Iustin Pop
    return FillIPolicy(self.ipolicy, ipolicy)
1759 918eb80b Agata Murawska
1760 5c947f38 Iustin Pop
1761 96acbc09 Michael Hanselmann
class BlockDevStatus(ConfigObject):
1762 96acbc09 Michael Hanselmann
  """Config object representing the status of a block device."""
1763 96acbc09 Michael Hanselmann
  __slots__ = [
1764 96acbc09 Michael Hanselmann
    "dev_path",
1765 96acbc09 Michael Hanselmann
    "major",
1766 96acbc09 Michael Hanselmann
    "minor",
1767 96acbc09 Michael Hanselmann
    "sync_percent",
1768 96acbc09 Michael Hanselmann
    "estimated_time",
1769 96acbc09 Michael Hanselmann
    "is_degraded",
1770 f208978a Michael Hanselmann
    "ldisk_status",
1771 96acbc09 Michael Hanselmann
    ]
1772 96acbc09 Michael Hanselmann
1773 96acbc09 Michael Hanselmann
1774 2d76b580 Michael Hanselmann
class ImportExportStatus(ConfigObject):
1775 2d76b580 Michael Hanselmann
  """Config object representing the status of an import or export."""
1776 2d76b580 Michael Hanselmann
  __slots__ = [
1777 2d76b580 Michael Hanselmann
    "recent_output",
1778 2d76b580 Michael Hanselmann
    "listen_port",
1779 2d76b580 Michael Hanselmann
    "connected",
1780 c08d76f5 Michael Hanselmann
    "progress_mbytes",
1781 c08d76f5 Michael Hanselmann
    "progress_throughput",
1782 c08d76f5 Michael Hanselmann
    "progress_eta",
1783 c08d76f5 Michael Hanselmann
    "progress_percent",
1784 2d76b580 Michael Hanselmann
    "exit_status",
1785 2d76b580 Michael Hanselmann
    "error_message",
1786 2d76b580 Michael Hanselmann
    ] + _TIMESTAMPS
1787 2d76b580 Michael Hanselmann
1788 2d76b580 Michael Hanselmann
1789 eb630f50 Michael Hanselmann
class ImportExportOptions(ConfigObject):
1790 eb630f50 Michael Hanselmann
  """Options for import/export daemon
1791 eb630f50 Michael Hanselmann

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

1799 eb630f50 Michael Hanselmann
  """
1800 eb630f50 Michael Hanselmann
  __slots__ = [
1801 eb630f50 Michael Hanselmann
    "key_name",
1802 eb630f50 Michael Hanselmann
    "ca_pem",
1803 a5310c2a Michael Hanselmann
    "compress",
1804 af1d39b1 Michael Hanselmann
    "magic",
1805 855d2fc7 Michael Hanselmann
    "ipv6",
1806 4478301b Michael Hanselmann
    "connect_timeout",
1807 eb630f50 Michael Hanselmann
    ]
1808 eb630f50 Michael Hanselmann
1809 eb630f50 Michael Hanselmann
1810 18d750b9 Guido Trotter
class ConfdRequest(ConfigObject):
1811 18d750b9 Guido Trotter
  """Object holding a confd request.
1812 18d750b9 Guido Trotter

1813 18d750b9 Guido Trotter
  @ivar protocol: confd protocol version
1814 18d750b9 Guido Trotter
  @ivar type: confd query type
1815 18d750b9 Guido Trotter
  @ivar query: query request
1816 18d750b9 Guido Trotter
  @ivar rsalt: requested reply salt
1817 18d750b9 Guido Trotter

1818 18d750b9 Guido Trotter
  """
1819 18d750b9 Guido Trotter
  __slots__ = [
1820 18d750b9 Guido Trotter
    "protocol",
1821 18d750b9 Guido Trotter
    "type",
1822 18d750b9 Guido Trotter
    "query",
1823 18d750b9 Guido Trotter
    "rsalt",
1824 18d750b9 Guido Trotter
    ]
1825 18d750b9 Guido Trotter
1826 18d750b9 Guido Trotter
1827 18d750b9 Guido Trotter
class ConfdReply(ConfigObject):
1828 18d750b9 Guido Trotter
  """Object holding a confd reply.
1829 18d750b9 Guido Trotter

1830 18d750b9 Guido Trotter
  @ivar protocol: confd protocol version
1831 18d750b9 Guido Trotter
  @ivar status: reply status code (ok, error)
1832 18d750b9 Guido Trotter
  @ivar answer: confd query reply
1833 18d750b9 Guido Trotter
  @ivar serial: configuration serial number
1834 18d750b9 Guido Trotter

1835 18d750b9 Guido Trotter
  """
1836 18d750b9 Guido Trotter
  __slots__ = [
1837 18d750b9 Guido Trotter
    "protocol",
1838 18d750b9 Guido Trotter
    "status",
1839 18d750b9 Guido Trotter
    "answer",
1840 18d750b9 Guido Trotter
    "serial",
1841 18d750b9 Guido Trotter
    ]
1842 18d750b9 Guido Trotter
1843 18d750b9 Guido Trotter
1844 707f23b5 Michael Hanselmann
class QueryFieldDefinition(ConfigObject):
1845 707f23b5 Michael Hanselmann
  """Object holding a query field definition.
1846 707f23b5 Michael Hanselmann

1847 24d6d3e2 Michael Hanselmann
  @ivar name: Field name
1848 707f23b5 Michael Hanselmann
  @ivar title: Human-readable title
1849 707f23b5 Michael Hanselmann
  @ivar kind: Field type
1850 1ae17369 Michael Hanselmann
  @ivar doc: Human-readable description
1851 707f23b5 Michael Hanselmann

1852 707f23b5 Michael Hanselmann
  """
1853 707f23b5 Michael Hanselmann
  __slots__ = [
1854 707f23b5 Michael Hanselmann
    "name",
1855 707f23b5 Michael Hanselmann
    "title",
1856 707f23b5 Michael Hanselmann
    "kind",
1857 1ae17369 Michael Hanselmann
    "doc",
1858 707f23b5 Michael Hanselmann
    ]
1859 707f23b5 Michael Hanselmann
1860 707f23b5 Michael Hanselmann
1861 0538c375 Michael Hanselmann
class _QueryResponseBase(ConfigObject):
1862 0538c375 Michael Hanselmann
  __slots__ = [
1863 0538c375 Michael Hanselmann
    "fields",
1864 0538c375 Michael Hanselmann
    ]
1865 0538c375 Michael Hanselmann
1866 0538c375 Michael Hanselmann
  def ToDict(self):
1867 0538c375 Michael Hanselmann
    """Custom function for serializing.
1868 0538c375 Michael Hanselmann

1869 0538c375 Michael Hanselmann
    """
1870 0538c375 Michael Hanselmann
    mydict = super(_QueryResponseBase, self).ToDict()
1871 0538c375 Michael Hanselmann
    mydict["fields"] = self._ContainerToDicts(mydict["fields"])
1872 0538c375 Michael Hanselmann
    return mydict
1873 0538c375 Michael Hanselmann
1874 0538c375 Michael Hanselmann
  @classmethod
1875 0538c375 Michael Hanselmann
  def FromDict(cls, val):
1876 0538c375 Michael Hanselmann
    """Custom function for de-serializing.
1877 0538c375 Michael Hanselmann

1878 0538c375 Michael Hanselmann
    """
1879 0538c375 Michael Hanselmann
    obj = super(_QueryResponseBase, cls).FromDict(val)
1880 0538c375 Michael Hanselmann
    obj.fields = cls._ContainerFromDicts(obj.fields, list, QueryFieldDefinition)
1881 0538c375 Michael Hanselmann
    return obj
1882 0538c375 Michael Hanselmann
1883 0538c375 Michael Hanselmann
1884 24d6d3e2 Michael Hanselmann
class QueryRequest(ConfigObject):
1885 24d6d3e2 Michael Hanselmann
  """Object holding a query request.
1886 24d6d3e2 Michael Hanselmann

1887 24d6d3e2 Michael Hanselmann
  """
1888 24d6d3e2 Michael Hanselmann
  __slots__ = [
1889 24d6d3e2 Michael Hanselmann
    "what",
1890 24d6d3e2 Michael Hanselmann
    "fields",
1891 2e5c33db Iustin Pop
    "qfilter",
1892 24d6d3e2 Michael Hanselmann
    ]
1893 24d6d3e2 Michael Hanselmann
1894 24d6d3e2 Michael Hanselmann
1895 0538c375 Michael Hanselmann
class QueryResponse(_QueryResponseBase):
1896 24d6d3e2 Michael Hanselmann
  """Object holding the response to a query.
1897 24d6d3e2 Michael Hanselmann

1898 24d6d3e2 Michael Hanselmann
  @ivar fields: List of L{QueryFieldDefinition} objects
1899 24d6d3e2 Michael Hanselmann
  @ivar data: Requested data
1900 24d6d3e2 Michael Hanselmann

1901 24d6d3e2 Michael Hanselmann
  """
1902 24d6d3e2 Michael Hanselmann
  __slots__ = [
1903 24d6d3e2 Michael Hanselmann
    "data",
1904 24d6d3e2 Michael Hanselmann
    ]
1905 24d6d3e2 Michael Hanselmann
1906 24d6d3e2 Michael Hanselmann
1907 24d6d3e2 Michael Hanselmann
class QueryFieldsRequest(ConfigObject):
1908 24d6d3e2 Michael Hanselmann
  """Object holding a request for querying available fields.
1909 24d6d3e2 Michael Hanselmann

1910 24d6d3e2 Michael Hanselmann
  """
1911 24d6d3e2 Michael Hanselmann
  __slots__ = [
1912 24d6d3e2 Michael Hanselmann
    "what",
1913 24d6d3e2 Michael Hanselmann
    "fields",
1914 24d6d3e2 Michael Hanselmann
    ]
1915 24d6d3e2 Michael Hanselmann
1916 24d6d3e2 Michael Hanselmann
1917 0538c375 Michael Hanselmann
class QueryFieldsResponse(_QueryResponseBase):
1918 24d6d3e2 Michael Hanselmann
  """Object holding the response to a query for fields.
1919 24d6d3e2 Michael Hanselmann

1920 24d6d3e2 Michael Hanselmann
  @ivar fields: List of L{QueryFieldDefinition} objects
1921 24d6d3e2 Michael Hanselmann

1922 24d6d3e2 Michael Hanselmann
  """
1923 24d6d3e2 Michael Hanselmann
  __slots__ = [
1924 24d6d3e2 Michael Hanselmann
    ]
1925 24d6d3e2 Michael Hanselmann
1926 24d6d3e2 Michael Hanselmann
1927 6a1434d7 Andrea Spadaccini
class MigrationStatus(ConfigObject):
1928 6a1434d7 Andrea Spadaccini
  """Object holding the status of a migration.
1929 6a1434d7 Andrea Spadaccini

1930 6a1434d7 Andrea Spadaccini
  """
1931 6a1434d7 Andrea Spadaccini
  __slots__ = [
1932 6a1434d7 Andrea Spadaccini
    "status",
1933 6a1434d7 Andrea Spadaccini
    "transferred_ram",
1934 6a1434d7 Andrea Spadaccini
    "total_ram",
1935 6a1434d7 Andrea Spadaccini
    ]
1936 6a1434d7 Andrea Spadaccini
1937 6a1434d7 Andrea Spadaccini
1938 25ce3ec4 Michael Hanselmann
class InstanceConsole(ConfigObject):
1939 25ce3ec4 Michael Hanselmann
  """Object describing how to access the console of an instance.
1940 25ce3ec4 Michael Hanselmann

1941 25ce3ec4 Michael Hanselmann
  """
1942 25ce3ec4 Michael Hanselmann
  __slots__ = [
1943 25ce3ec4 Michael Hanselmann
    "instance",
1944 25ce3ec4 Michael Hanselmann
    "kind",
1945 25ce3ec4 Michael Hanselmann
    "message",
1946 25ce3ec4 Michael Hanselmann
    "host",
1947 25ce3ec4 Michael Hanselmann
    "port",
1948 25ce3ec4 Michael Hanselmann
    "user",
1949 25ce3ec4 Michael Hanselmann
    "command",
1950 25ce3ec4 Michael Hanselmann
    "display",
1951 25ce3ec4 Michael Hanselmann
    ]
1952 25ce3ec4 Michael Hanselmann
1953 25ce3ec4 Michael Hanselmann
  def Validate(self):
1954 25ce3ec4 Michael Hanselmann
    """Validates contents of this object.
1955 25ce3ec4 Michael Hanselmann

1956 25ce3ec4 Michael Hanselmann
    """
1957 25ce3ec4 Michael Hanselmann
    assert self.kind in constants.CONS_ALL, "Unknown console type"
1958 25ce3ec4 Michael Hanselmann
    assert self.instance, "Missing instance name"
1959 4d2cdb5a Andrea Spadaccini
    assert self.message or self.kind in [constants.CONS_SSH,
1960 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1961 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_VNC]
1962 25ce3ec4 Michael Hanselmann
    assert self.host or self.kind == constants.CONS_MESSAGE
1963 25ce3ec4 Michael Hanselmann
    assert self.port or self.kind in [constants.CONS_MESSAGE,
1964 25ce3ec4 Michael Hanselmann
                                      constants.CONS_SSH]
1965 25ce3ec4 Michael Hanselmann
    assert self.user or self.kind in [constants.CONS_MESSAGE,
1966 4d2cdb5a Andrea Spadaccini
                                      constants.CONS_SPICE,
1967 25ce3ec4 Michael Hanselmann
                                      constants.CONS_VNC]
1968 25ce3ec4 Michael Hanselmann
    assert self.command or self.kind in [constants.CONS_MESSAGE,
1969 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1970 25ce3ec4 Michael Hanselmann
                                         constants.CONS_VNC]
1971 25ce3ec4 Michael Hanselmann
    assert self.display or self.kind in [constants.CONS_MESSAGE,
1972 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1973 25ce3ec4 Michael Hanselmann
                                         constants.CONS_SSH]
1974 25ce3ec4 Michael Hanselmann
    return True
1975 25ce3ec4 Michael Hanselmann
1976 25ce3ec4 Michael Hanselmann
1977 a8083063 Iustin Pop
class SerializableConfigParser(ConfigParser.SafeConfigParser):
1978 a8083063 Iustin Pop
  """Simple wrapper over ConfigParse that allows serialization.
1979 a8083063 Iustin Pop

1980 a8083063 Iustin Pop
  This class is basically ConfigParser.SafeConfigParser with two
1981 a8083063 Iustin Pop
  additional methods that allow it to serialize/unserialize to/from a
1982 a8083063 Iustin Pop
  buffer.
1983 a8083063 Iustin Pop

1984 a8083063 Iustin Pop
  """
1985 a8083063 Iustin Pop
  def Dumps(self):
1986 a8083063 Iustin Pop
    """Dump this instance and return the string representation."""
1987 a8083063 Iustin Pop
    buf = StringIO()
1988 a8083063 Iustin Pop
    self.write(buf)
1989 a8083063 Iustin Pop
    return buf.getvalue()
1990 a8083063 Iustin Pop
1991 b39bf4bb Guido Trotter
  @classmethod
1992 b39bf4bb Guido Trotter
  def Loads(cls, data):
1993 a8083063 Iustin Pop
    """Load data from a string."""
1994 a8083063 Iustin Pop
    buf = StringIO(data)
1995 b39bf4bb Guido Trotter
    cfp = cls()
1996 a8083063 Iustin Pop
    cfp.readfp(buf)
1997 a8083063 Iustin Pop
    return cfp