Statistics
| Branch: | Tag: | Revision:

root / lib / objects.py @ 57dc299a

History | View | Annotate | Download (54.7 kB)

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

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

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

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

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

98 918eb80b Agata Murawska
  """
99 2cc673a3 Iustin Pop
  assert frozenset(default_ipolicy.keys()) == constants.IPOLICY_ALL_KEYS
100 918eb80b Agata Murawska
  ret_dict = {}
101 2cc673a3 Iustin Pop
  for key in constants.IPOLICY_PARAMETERS:
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 2cc673a3 Iustin Pop
  for key in [constants.ISPECS_DTS]:
107 2cc673a3 Iustin Pop
    ret_dict[key] = list(custom_ipolicy.get(key, default_ipolicy[key]))
108 2cc673a3 Iustin Pop
109 918eb80b Agata Murawska
  return ret_dict
110 918eb80b Agata Murawska
111 918eb80b Agata Murawska
112 6e34b628 Guido Trotter
def UpgradeGroupedParams(target, defaults):
113 6e34b628 Guido Trotter
  """Update all groups for the target parameter.
114 6e34b628 Guido Trotter

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

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

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

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

146 bc5d0215 Andrea Spadaccini
  @type diskparams: dict
147 bc5d0215 Andrea Spadaccini
  @param diskparams: disk parameters to upgrade
148 bc5d0215 Andrea Spadaccini
  @rtype: dict
149 bc5d0215 Andrea Spadaccini
  @return: the upgraded disk parameters dit
150 bc5d0215 Andrea Spadaccini

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

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

191 2cc673a3 Iustin Pop
  @param fill_all: whether for cluster policies we should ensure that
192 2cc673a3 Iustin Pop
    all values are filled
193 32017174 Agata Murawska

194 32017174 Agata Murawska

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

235 a8083063 Iustin Pop
  It has the following properties:
236 a8083063 Iustin Pop

237 a8083063 Iustin Pop
    - provides somewhat safe recursive unpickling and pickling for its classes
238 a8083063 Iustin Pop
    - unset attributes which are defined in slots are always returned
239 a8083063 Iustin Pop
      as None instead of raising an error
240 a8083063 Iustin Pop

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

244 a8083063 Iustin Pop
  """
245 a8083063 Iustin Pop
  __slots__ = []
246 a8083063 Iustin Pop
247 a8083063 Iustin Pop
  def __init__(self, **kwargs):
248 319856a9 Michael Hanselmann
    for k, v in kwargs.iteritems():
249 319856a9 Michael Hanselmann
      setattr(self, k, v)
250 a8083063 Iustin Pop
251 a8083063 Iustin Pop
  def __getattr__(self, name):
252 adf385c7 Iustin Pop
    if name not in self._all_slots():
253 3ecf6786 Iustin Pop
      raise AttributeError("Invalid object attribute %s.%s" %
254 3ecf6786 Iustin Pop
                           (type(self).__name__, name))
255 a8083063 Iustin Pop
    return None
256 a8083063 Iustin Pop
257 a8083063 Iustin Pop
  def __setstate__(self, state):
258 adf385c7 Iustin Pop
    slots = self._all_slots()
259 a8083063 Iustin Pop
    for name in state:
260 adf385c7 Iustin Pop
      if name in slots:
261 a8083063 Iustin Pop
        setattr(self, name, state[name])
262 a8083063 Iustin Pop
263 adf385c7 Iustin Pop
  @classmethod
264 adf385c7 Iustin Pop
  def _all_slots(cls):
265 adf385c7 Iustin Pop
    """Compute the list of all declared slots for a class.
266 adf385c7 Iustin Pop

267 adf385c7 Iustin Pop
    """
268 adf385c7 Iustin Pop
    slots = []
269 adf385c7 Iustin Pop
    for parent in cls.__mro__:
270 adf385c7 Iustin Pop
      slots.extend(getattr(parent, "__slots__", []))
271 adf385c7 Iustin Pop
    return slots
272 adf385c7 Iustin Pop
273 ff9c047c Iustin Pop
  def ToDict(self):
274 ff9c047c Iustin Pop
    """Convert to a dict holding only standard python types.
275 ff9c047c Iustin Pop

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

282 ff9c047c Iustin Pop
    """
283 4c14965f Guido Trotter
    result = {}
284 adf385c7 Iustin Pop
    for name in self._all_slots():
285 4c14965f Guido Trotter
      value = getattr(self, name, None)
286 4c14965f Guido Trotter
      if value is not None:
287 4c14965f Guido Trotter
        result[name] = value
288 4c14965f Guido Trotter
    return result
289 4c14965f Guido Trotter
290 4c14965f Guido Trotter
  __getstate__ = ToDict
291 ff9c047c Iustin Pop
292 ff9c047c Iustin Pop
  @classmethod
293 ff9c047c Iustin Pop
  def FromDict(cls, val):
294 ff9c047c Iustin Pop
    """Create an object from a dictionary.
295 ff9c047c Iustin Pop

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

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

304 ff9c047c Iustin Pop
    """
305 ff9c047c Iustin Pop
    if not isinstance(val, dict):
306 ff9c047c Iustin Pop
      raise errors.ConfigurationError("Invalid object passed to FromDict:"
307 ff9c047c Iustin Pop
                                      " expected dict, got %s" % type(val))
308 319856a9 Michael Hanselmann
    val_str = dict([(str(k), v) for k, v in val.iteritems()])
309 b459a848 Andrea Spadaccini
    obj = cls(**val_str) # pylint: disable=W0142
310 ff9c047c Iustin Pop
    return obj
311 ff9c047c Iustin Pop
312 ff9c047c Iustin Pop
  @staticmethod
313 ff9c047c Iustin Pop
  def _ContainerToDicts(container):
314 ff9c047c Iustin Pop
    """Convert the elements of a container to standard python types.
315 ff9c047c Iustin Pop

316 ff9c047c Iustin Pop
    This method converts a container with elements derived from
317 ff9c047c Iustin Pop
    ConfigData to standard python types. If the container is a dict,
318 ff9c047c Iustin Pop
    we don't touch the keys, only the values.
319 ff9c047c Iustin Pop

320 ff9c047c Iustin Pop
    """
321 ff9c047c Iustin Pop
    if isinstance(container, dict):
322 ff9c047c Iustin Pop
      ret = dict([(k, v.ToDict()) for k, v in container.iteritems()])
323 ff9c047c Iustin Pop
    elif isinstance(container, (list, tuple, set, frozenset)):
324 ff9c047c Iustin Pop
      ret = [elem.ToDict() for elem in container]
325 ff9c047c Iustin Pop
    else:
326 ff9c047c Iustin Pop
      raise TypeError("Invalid type %s passed to _ContainerToDicts" %
327 ff9c047c Iustin Pop
                      type(container))
328 ff9c047c Iustin Pop
    return ret
329 ff9c047c Iustin Pop
330 ff9c047c Iustin Pop
  @staticmethod
331 ff9c047c Iustin Pop
  def _ContainerFromDicts(source, c_type, e_type):
332 ff9c047c Iustin Pop
    """Convert a container from standard python types.
333 ff9c047c Iustin Pop

334 ff9c047c Iustin Pop
    This method converts a container with standard python types to
335 ff9c047c Iustin Pop
    ConfigData objects. If the container is a dict, we don't touch the
336 ff9c047c Iustin Pop
    keys, only the values.
337 ff9c047c Iustin Pop

338 ff9c047c Iustin Pop
    """
339 ff9c047c Iustin Pop
    if not isinstance(c_type, type):
340 ff9c047c Iustin Pop
      raise TypeError("Container type %s passed to _ContainerFromDicts is"
341 ff9c047c Iustin Pop
                      " not a type" % type(c_type))
342 fe25a79a Guido Trotter
    if source is None:
343 fe25a79a Guido Trotter
      source = c_type()
344 ff9c047c Iustin Pop
    if c_type is dict:
345 ff9c047c Iustin Pop
      ret = dict([(k, e_type.FromDict(v)) for k, v in source.iteritems()])
346 ff9c047c Iustin Pop
    elif c_type in (list, tuple, set, frozenset):
347 ff9c047c Iustin Pop
      ret = c_type([e_type.FromDict(elem) for elem in source])
348 ff9c047c Iustin Pop
    else:
349 ff9c047c Iustin Pop
      raise TypeError("Invalid container type %s passed to"
350 ff9c047c Iustin Pop
                      " _ContainerFromDicts" % c_type)
351 ff9c047c Iustin Pop
    return ret
352 ff9c047c Iustin Pop
353 e8d563f3 Iustin Pop
  def Copy(self):
354 e8d563f3 Iustin Pop
    """Makes a deep copy of the current object and its children.
355 e8d563f3 Iustin Pop

356 e8d563f3 Iustin Pop
    """
357 e8d563f3 Iustin Pop
    dict_form = self.ToDict()
358 e8d563f3 Iustin Pop
    clone_obj = self.__class__.FromDict(dict_form)
359 e8d563f3 Iustin Pop
    return clone_obj
360 e8d563f3 Iustin Pop
361 ff9c047c Iustin Pop
  def __repr__(self):
362 ff9c047c Iustin Pop
    """Implement __repr__ for ConfigObjects."""
363 ff9c047c Iustin Pop
    return repr(self.ToDict())
364 ff9c047c Iustin Pop
365 560428be Guido Trotter
  def UpgradeConfig(self):
366 560428be Guido Trotter
    """Fill defaults for missing configuration values.
367 560428be Guido Trotter

368 90d726a8 Iustin Pop
    This method will be called at configuration load time, and its
369 90d726a8 Iustin Pop
    implementation will be object dependent.
370 560428be Guido Trotter

371 560428be Guido Trotter
    """
372 560428be Guido Trotter
    pass
373 560428be Guido Trotter
374 a8083063 Iustin Pop
375 ec29fe40 Iustin Pop
class TaggableObject(ConfigObject):
376 5c947f38 Iustin Pop
  """An generic class supporting tags.
377 5c947f38 Iustin Pop

378 5c947f38 Iustin Pop
  """
379 154b9580 Balazs Lecz
  __slots__ = ["tags"]
380 b5e5632e Iustin Pop
  VALID_TAG_RE = re.compile("^[\w.+*/:@-]+$")
381 2057f6c7 Iustin Pop
382 b5e5632e Iustin Pop
  @classmethod
383 b5e5632e Iustin Pop
  def ValidateTag(cls, tag):
384 5c947f38 Iustin Pop
    """Check if a tag is valid.
385 5c947f38 Iustin Pop

386 5c947f38 Iustin Pop
    If the tag is invalid, an errors.TagError will be raised. The
387 5c947f38 Iustin Pop
    function has no return value.
388 5c947f38 Iustin Pop

389 5c947f38 Iustin Pop
    """
390 5c947f38 Iustin Pop
    if not isinstance(tag, basestring):
391 3ecf6786 Iustin Pop
      raise errors.TagError("Invalid tag type (not a string)")
392 5c947f38 Iustin Pop
    if len(tag) > constants.MAX_TAG_LEN:
393 319856a9 Michael Hanselmann
      raise errors.TagError("Tag too long (>%d characters)" %
394 319856a9 Michael Hanselmann
                            constants.MAX_TAG_LEN)
395 5c947f38 Iustin Pop
    if not tag:
396 3ecf6786 Iustin Pop
      raise errors.TagError("Tags cannot be empty")
397 b5e5632e Iustin Pop
    if not cls.VALID_TAG_RE.match(tag):
398 3ecf6786 Iustin Pop
      raise errors.TagError("Tag contains invalid characters")
399 5c947f38 Iustin Pop
400 5c947f38 Iustin Pop
  def GetTags(self):
401 5c947f38 Iustin Pop
    """Return the tags list.
402 5c947f38 Iustin Pop

403 5c947f38 Iustin Pop
    """
404 5c947f38 Iustin Pop
    tags = getattr(self, "tags", None)
405 5c947f38 Iustin Pop
    if tags is None:
406 5c947f38 Iustin Pop
      tags = self.tags = set()
407 5c947f38 Iustin Pop
    return tags
408 5c947f38 Iustin Pop
409 5c947f38 Iustin Pop
  def AddTag(self, tag):
410 5c947f38 Iustin Pop
    """Add a new tag.
411 5c947f38 Iustin Pop

412 5c947f38 Iustin Pop
    """
413 5c947f38 Iustin Pop
    self.ValidateTag(tag)
414 5c947f38 Iustin Pop
    tags = self.GetTags()
415 5c947f38 Iustin Pop
    if len(tags) >= constants.MAX_TAGS_PER_OBJ:
416 3ecf6786 Iustin Pop
      raise errors.TagError("Too many tags")
417 5c947f38 Iustin Pop
    self.GetTags().add(tag)
418 5c947f38 Iustin Pop
419 5c947f38 Iustin Pop
  def RemoveTag(self, tag):
420 5c947f38 Iustin Pop
    """Remove a 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
    try:
426 5c947f38 Iustin Pop
      tags.remove(tag)
427 5c947f38 Iustin Pop
    except KeyError:
428 3ecf6786 Iustin Pop
      raise errors.TagError("Tag not found")
429 5c947f38 Iustin Pop
430 ff9c047c Iustin Pop
  def ToDict(self):
431 ff9c047c Iustin Pop
    """Taggable-object-specific conversion to standard python types.
432 ff9c047c Iustin Pop

433 ff9c047c Iustin Pop
    This replaces the tags set with a list.
434 ff9c047c Iustin Pop

435 ff9c047c Iustin Pop
    """
436 ff9c047c Iustin Pop
    bo = super(TaggableObject, self).ToDict()
437 ff9c047c Iustin Pop
438 ff9c047c Iustin Pop
    tags = bo.get("tags", None)
439 ff9c047c Iustin Pop
    if isinstance(tags, set):
440 ff9c047c Iustin Pop
      bo["tags"] = list(tags)
441 ff9c047c Iustin Pop
    return bo
442 ff9c047c Iustin Pop
443 ff9c047c Iustin Pop
  @classmethod
444 ff9c047c Iustin Pop
  def FromDict(cls, val):
445 ff9c047c Iustin Pop
    """Custom function for instances.
446 ff9c047c Iustin Pop

447 ff9c047c Iustin Pop
    """
448 ff9c047c Iustin Pop
    obj = super(TaggableObject, cls).FromDict(val)
449 ff9c047c Iustin Pop
    if hasattr(obj, "tags") and isinstance(obj.tags, list):
450 ff9c047c Iustin Pop
      obj.tags = set(obj.tags)
451 ff9c047c Iustin Pop
    return obj
452 ff9c047c Iustin Pop
453 5c947f38 Iustin Pop
454 061af273 Andrea Spadaccini
class MasterNetworkParameters(ConfigObject):
455 061af273 Andrea Spadaccini
  """Network configuration parameters for the master
456 061af273 Andrea Spadaccini

457 061af273 Andrea Spadaccini
  @ivar name: master name
458 061af273 Andrea Spadaccini
  @ivar ip: master IP
459 061af273 Andrea Spadaccini
  @ivar netmask: master netmask
460 061af273 Andrea Spadaccini
  @ivar netdev: master network device
461 061af273 Andrea Spadaccini
  @ivar ip_family: master IP family
462 061af273 Andrea Spadaccini

463 061af273 Andrea Spadaccini
  """
464 061af273 Andrea Spadaccini
  __slots__ = [
465 061af273 Andrea Spadaccini
    "name",
466 061af273 Andrea Spadaccini
    "ip",
467 061af273 Andrea Spadaccini
    "netmask",
468 061af273 Andrea Spadaccini
    "netdev",
469 061af273 Andrea Spadaccini
    "ip_family"
470 061af273 Andrea Spadaccini
    ]
471 061af273 Andrea Spadaccini
472 061af273 Andrea Spadaccini
473 a8083063 Iustin Pop
class ConfigData(ConfigObject):
474 a8083063 Iustin Pop
  """Top-level config object."""
475 3df43542 Guido Trotter
  __slots__ = [
476 3df43542 Guido Trotter
    "version",
477 3df43542 Guido Trotter
    "cluster",
478 3df43542 Guido Trotter
    "nodes",
479 3df43542 Guido Trotter
    "nodegroups",
480 3df43542 Guido Trotter
    "instances",
481 3df43542 Guido Trotter
    "serial_no",
482 3df43542 Guido Trotter
    ] + _TIMESTAMPS
483 a8083063 Iustin Pop
484 ff9c047c Iustin Pop
  def ToDict(self):
485 ff9c047c Iustin Pop
    """Custom function for top-level config data.
486 ff9c047c Iustin Pop

487 ff9c047c Iustin Pop
    This just replaces the list of instances, nodes and the cluster
488 ff9c047c Iustin Pop
    with standard python types.
489 ff9c047c Iustin Pop

490 ff9c047c Iustin Pop
    """
491 ff9c047c Iustin Pop
    mydict = super(ConfigData, self).ToDict()
492 ff9c047c Iustin Pop
    mydict["cluster"] = mydict["cluster"].ToDict()
493 3df43542 Guido Trotter
    for key in "nodes", "instances", "nodegroups":
494 ff9c047c Iustin Pop
      mydict[key] = self._ContainerToDicts(mydict[key])
495 ff9c047c Iustin Pop
496 ff9c047c Iustin Pop
    return mydict
497 ff9c047c Iustin Pop
498 ff9c047c Iustin Pop
  @classmethod
499 ff9c047c Iustin Pop
  def FromDict(cls, val):
500 ff9c047c Iustin Pop
    """Custom function for top-level config data
501 ff9c047c Iustin Pop

502 ff9c047c Iustin Pop
    """
503 ff9c047c Iustin Pop
    obj = super(ConfigData, cls).FromDict(val)
504 ff9c047c Iustin Pop
    obj.cluster = Cluster.FromDict(obj.cluster)
505 ff9c047c Iustin Pop
    obj.nodes = cls._ContainerFromDicts(obj.nodes, dict, Node)
506 ff9c047c Iustin Pop
    obj.instances = cls._ContainerFromDicts(obj.instances, dict, Instance)
507 3df43542 Guido Trotter
    obj.nodegroups = cls._ContainerFromDicts(obj.nodegroups, dict, NodeGroup)
508 ff9c047c Iustin Pop
    return obj
509 ff9c047c Iustin Pop
510 51cb1581 Luca Bigliardi
  def HasAnyDiskOfType(self, dev_type):
511 51cb1581 Luca Bigliardi
    """Check if in there is at disk of the given type in the configuration.
512 51cb1581 Luca Bigliardi

513 51cb1581 Luca Bigliardi
    @type dev_type: L{constants.LDS_BLOCK}
514 51cb1581 Luca Bigliardi
    @param dev_type: the type to look for
515 51cb1581 Luca Bigliardi
    @rtype: boolean
516 51cb1581 Luca Bigliardi
    @return: boolean indicating if a disk of the given type was found or not
517 51cb1581 Luca Bigliardi

518 51cb1581 Luca Bigliardi
    """
519 51cb1581 Luca Bigliardi
    for instance in self.instances.values():
520 51cb1581 Luca Bigliardi
      for disk in instance.disks:
521 51cb1581 Luca Bigliardi
        if disk.IsBasedOnDiskType(dev_type):
522 51cb1581 Luca Bigliardi
          return True
523 51cb1581 Luca Bigliardi
    return False
524 51cb1581 Luca Bigliardi
525 90d726a8 Iustin Pop
  def UpgradeConfig(self):
526 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
527 90d726a8 Iustin Pop

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

554 255e19d4 Guido Trotter
    @type nicparams:  dict
555 255e19d4 Guido Trotter
    @param nicparams: dictionary with parameter names/value
556 255e19d4 Guido Trotter
    @raise errors.ConfigurationError: when a parameter is not valid
557 255e19d4 Guido Trotter

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

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

594 e51db2a6 Iustin Pop
    @warning: The path returned is not a normalized pathname; callers
595 e51db2a6 Iustin Pop
        should check that it is a valid path.
596 e51db2a6 Iustin Pop

597 222f2dd5 Iustin Pop
    """
598 222f2dd5 Iustin Pop
    if self.dev_type == constants.LD_LV:
599 222f2dd5 Iustin Pop
      return "/dev/%s/%s" % (self.logical_id[0], self.logical_id[1])
600 b6135bbc Apollon Oikonomopoulos
    elif self.dev_type == constants.LD_BLOCKDEV:
601 b6135bbc Apollon Oikonomopoulos
      return self.logical_id[1]
602 222f2dd5 Iustin Pop
    return None
603 222f2dd5 Iustin Pop
604 fc1dc9d7 Iustin Pop
  def ChildrenNeeded(self):
605 fc1dc9d7 Iustin Pop
    """Compute the needed number of children for activation.
606 fc1dc9d7 Iustin Pop

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

611 fc1dc9d7 Iustin Pop
    Currently, only DRBD8 supports diskless activation (therefore we
612 fc1dc9d7 Iustin Pop
    return 0), for all other we keep the previous semantics and return
613 fc1dc9d7 Iustin Pop
    -1.
614 fc1dc9d7 Iustin Pop

615 fc1dc9d7 Iustin Pop
    """
616 fc1dc9d7 Iustin Pop
    if self.dev_type == constants.LD_DRBD8:
617 fc1dc9d7 Iustin Pop
      return 0
618 fc1dc9d7 Iustin Pop
    return -1
619 fc1dc9d7 Iustin Pop
620 51cb1581 Luca Bigliardi
  def IsBasedOnDiskType(self, dev_type):
621 51cb1581 Luca Bigliardi
    """Check if the disk or its children are based on the given type.
622 51cb1581 Luca Bigliardi

623 51cb1581 Luca Bigliardi
    @type dev_type: L{constants.LDS_BLOCK}
624 51cb1581 Luca Bigliardi
    @param dev_type: the type to look for
625 51cb1581 Luca Bigliardi
    @rtype: boolean
626 51cb1581 Luca Bigliardi
    @return: boolean indicating if a device of the given type was found or not
627 51cb1581 Luca Bigliardi

628 51cb1581 Luca Bigliardi
    """
629 51cb1581 Luca Bigliardi
    if self.children:
630 51cb1581 Luca Bigliardi
      for child in self.children:
631 51cb1581 Luca Bigliardi
        if child.IsBasedOnDiskType(dev_type):
632 51cb1581 Luca Bigliardi
          return True
633 51cb1581 Luca Bigliardi
    return self.dev_type == dev_type
634 51cb1581 Luca Bigliardi
635 a8083063 Iustin Pop
  def GetNodes(self, node):
636 a8083063 Iustin Pop
    """This function returns the nodes this device lives on.
637 a8083063 Iustin Pop

638 a8083063 Iustin Pop
    Given the node on which the parent of the device lives on (or, in
639 a8083063 Iustin Pop
    case of a top-level device, the primary node of the devices'
640 a8083063 Iustin Pop
    instance), this function will return a list of nodes on which this
641 a8083063 Iustin Pop
    devices needs to (or can) be assembled.
642 a8083063 Iustin Pop

643 a8083063 Iustin Pop
    """
644 b6135bbc Apollon Oikonomopoulos
    if self.dev_type in [constants.LD_LV, constants.LD_FILE,
645 b6135bbc Apollon Oikonomopoulos
                         constants.LD_BLOCKDEV]:
646 a8083063 Iustin Pop
      result = [node]
647 a1f445d3 Iustin Pop
    elif self.dev_type in constants.LDS_DRBD:
648 a8083063 Iustin Pop
      result = [self.logical_id[0], self.logical_id[1]]
649 a8083063 Iustin Pop
      if node not in result:
650 3ecf6786 Iustin Pop
        raise errors.ConfigurationError("DRBD device passed unknown node")
651 a8083063 Iustin Pop
    else:
652 3ecf6786 Iustin Pop
      raise errors.ProgrammerError("Unhandled device type %s" % self.dev_type)
653 a8083063 Iustin Pop
    return result
654 a8083063 Iustin Pop
655 a8083063 Iustin Pop
  def ComputeNodeTree(self, parent_node):
656 a8083063 Iustin Pop
    """Compute the node/disk tree for this disk and its children.
657 a8083063 Iustin Pop

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

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

693 6d33a6eb Iustin Pop
    This only works for VG-based disks.
694 6d33a6eb Iustin Pop

695 6d33a6eb Iustin Pop
    @type amount: integer
696 6d33a6eb Iustin Pop
    @param amount: the desired increase in (user-visible) disk space
697 6d33a6eb Iustin Pop
    @rtype: dict
698 6d33a6eb Iustin Pop
    @return: a dictionary of volume-groups and the required size
699 6d33a6eb Iustin Pop

700 6d33a6eb Iustin Pop
    """
701 6d33a6eb Iustin Pop
    if self.dev_type == constants.LD_LV:
702 6d33a6eb Iustin Pop
      return {self.logical_id[0]: amount}
703 6d33a6eb Iustin Pop
    elif self.dev_type == constants.LD_DRBD8:
704 6d33a6eb Iustin Pop
      if self.children:
705 6d33a6eb Iustin Pop
        return self.children[0].ComputeGrowth(amount)
706 6d33a6eb Iustin Pop
      else:
707 6d33a6eb Iustin Pop
        return {}
708 6d33a6eb Iustin Pop
    else:
709 6d33a6eb Iustin Pop
      # Other disk types do not require VG space
710 6d33a6eb Iustin Pop
      return {}
711 6d33a6eb Iustin Pop
712 acec9d51 Iustin Pop
  def RecordGrow(self, amount):
713 acec9d51 Iustin Pop
    """Update the size of this disk after growth.
714 acec9d51 Iustin Pop

715 acec9d51 Iustin Pop
    This method recurses over the disks's children and updates their
716 acec9d51 Iustin Pop
    size correspondigly. The method needs to be kept in sync with the
717 acec9d51 Iustin Pop
    actual algorithms from bdev.
718 acec9d51 Iustin Pop

719 acec9d51 Iustin Pop
    """
720 4b97f902 Apollon Oikonomopoulos
    if self.dev_type in (constants.LD_LV, constants.LD_FILE):
721 acec9d51 Iustin Pop
      self.size += amount
722 acec9d51 Iustin Pop
    elif self.dev_type == constants.LD_DRBD8:
723 acec9d51 Iustin Pop
      if self.children:
724 acec9d51 Iustin Pop
        self.children[0].RecordGrow(amount)
725 acec9d51 Iustin Pop
      self.size += amount
726 acec9d51 Iustin Pop
    else:
727 acec9d51 Iustin Pop
      raise errors.ProgrammerError("Disk.RecordGrow called for unsupported"
728 acec9d51 Iustin Pop
                                   " disk type %s" % self.dev_type)
729 acec9d51 Iustin Pop
730 a805ec18 Iustin Pop
  def UnsetSize(self):
731 a805ec18 Iustin Pop
    """Sets recursively the size to zero for the disk and its children.
732 a805ec18 Iustin Pop

733 a805ec18 Iustin Pop
    """
734 a805ec18 Iustin Pop
    if self.children:
735 a805ec18 Iustin Pop
      for child in self.children:
736 a805ec18 Iustin Pop
        child.UnsetSize()
737 a805ec18 Iustin Pop
    self.size = 0
738 a805ec18 Iustin Pop
739 0402302c Iustin Pop
  def SetPhysicalID(self, target_node, nodes_ip):
740 0402302c Iustin Pop
    """Convert the logical ID to the physical ID.
741 0402302c Iustin Pop

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

744 0402302c Iustin Pop
    The routine descends down and updates its children also, because
745 0402302c Iustin Pop
    this helps when the only the top device is passed to the remote
746 0402302c Iustin Pop
    node.
747 0402302c Iustin Pop

748 0402302c Iustin Pop
    Arguments:
749 0402302c Iustin Pop
      - target_node: the node we wish to configure for
750 0402302c Iustin Pop
      - nodes_ip: a mapping of node name to ip
751 0402302c Iustin Pop

752 0402302c Iustin Pop
    The target_node must exist in in nodes_ip, and must be one of the
753 0402302c Iustin Pop
    nodes in the logical ID for each of the DRBD devices encountered
754 0402302c Iustin Pop
    in the disk tree.
755 0402302c Iustin Pop

756 0402302c Iustin Pop
    """
757 0402302c Iustin Pop
    if self.children:
758 0402302c Iustin Pop
      for child in self.children:
759 0402302c Iustin Pop
        child.SetPhysicalID(target_node, nodes_ip)
760 0402302c Iustin Pop
761 0402302c Iustin Pop
    if self.logical_id is None and self.physical_id is not None:
762 0402302c Iustin Pop
      return
763 0402302c Iustin Pop
    if self.dev_type in constants.LDS_DRBD:
764 f9518d38 Iustin Pop
      pnode, snode, port, pminor, sminor, secret = self.logical_id
765 0402302c Iustin Pop
      if target_node not in (pnode, snode):
766 0402302c Iustin Pop
        raise errors.ConfigurationError("DRBD device not knowing node %s" %
767 0402302c Iustin Pop
                                        target_node)
768 0402302c Iustin Pop
      pnode_ip = nodes_ip.get(pnode, None)
769 0402302c Iustin Pop
      snode_ip = nodes_ip.get(snode, None)
770 0402302c Iustin Pop
      if pnode_ip is None or snode_ip is None:
771 0402302c Iustin Pop
        raise errors.ConfigurationError("Can't find primary or secondary node"
772 0402302c Iustin Pop
                                        " for %s" % str(self))
773 ffa1c0dc Iustin Pop
      p_data = (pnode_ip, port)
774 ffa1c0dc Iustin Pop
      s_data = (snode_ip, port)
775 0402302c Iustin Pop
      if pnode == target_node:
776 f9518d38 Iustin Pop
        self.physical_id = p_data + s_data + (pminor, secret)
777 0402302c Iustin Pop
      else: # it must be secondary, we tested above
778 f9518d38 Iustin Pop
        self.physical_id = s_data + p_data + (sminor, secret)
779 0402302c Iustin Pop
    else:
780 0402302c Iustin Pop
      self.physical_id = self.logical_id
781 0402302c Iustin Pop
    return
782 0402302c Iustin Pop
783 ff9c047c Iustin Pop
  def ToDict(self):
784 ff9c047c Iustin Pop
    """Disk-specific conversion to standard python types.
785 ff9c047c Iustin Pop

786 ff9c047c Iustin Pop
    This replaces the children lists of objects with lists of
787 ff9c047c Iustin Pop
    standard python types.
788 ff9c047c Iustin Pop

789 ff9c047c Iustin Pop
    """
790 ff9c047c Iustin Pop
    bo = super(Disk, self).ToDict()
791 ff9c047c Iustin Pop
792 ff9c047c Iustin Pop
    for attr in ("children",):
793 ff9c047c Iustin Pop
      alist = bo.get(attr, None)
794 ff9c047c Iustin Pop
      if alist:
795 ff9c047c Iustin Pop
        bo[attr] = self._ContainerToDicts(alist)
796 ff9c047c Iustin Pop
    return bo
797 ff9c047c Iustin Pop
798 ff9c047c Iustin Pop
  @classmethod
799 ff9c047c Iustin Pop
  def FromDict(cls, val):
800 ff9c047c Iustin Pop
    """Custom function for Disks
801 ff9c047c Iustin Pop

802 ff9c047c Iustin Pop
    """
803 ff9c047c Iustin Pop
    obj = super(Disk, cls).FromDict(val)
804 ff9c047c Iustin Pop
    if obj.children:
805 ff9c047c Iustin Pop
      obj.children = cls._ContainerFromDicts(obj.children, list, Disk)
806 ff9c047c Iustin Pop
    if obj.logical_id and isinstance(obj.logical_id, list):
807 ff9c047c Iustin Pop
      obj.logical_id = tuple(obj.logical_id)
808 ff9c047c Iustin Pop
    if obj.physical_id and isinstance(obj.physical_id, list):
809 ff9c047c Iustin Pop
      obj.physical_id = tuple(obj.physical_id)
810 f9518d38 Iustin Pop
    if obj.dev_type in constants.LDS_DRBD:
811 f9518d38 Iustin Pop
      # we need a tuple of length six here
812 f9518d38 Iustin Pop
      if len(obj.logical_id) < 6:
813 f9518d38 Iustin Pop
        obj.logical_id += (None,) * (6 - len(obj.logical_id))
814 ff9c047c Iustin Pop
    return obj
815 ff9c047c Iustin Pop
816 65a15336 Iustin Pop
  def __str__(self):
817 65a15336 Iustin Pop
    """Custom str() formatter for disks.
818 65a15336 Iustin Pop

819 65a15336 Iustin Pop
    """
820 65a15336 Iustin Pop
    if self.dev_type == constants.LD_LV:
821 e687ec01 Michael Hanselmann
      val = "<LogicalVolume(/dev/%s/%s" % self.logical_id
822 65a15336 Iustin Pop
    elif self.dev_type in constants.LDS_DRBD:
823 89f28b76 Iustin Pop
      node_a, node_b, port, minor_a, minor_b = self.logical_id[:5]
824 00fb8246 Michael Hanselmann
      val = "<DRBD8("
825 073ca59e Iustin Pop
      if self.physical_id is None:
826 073ca59e Iustin Pop
        phy = "unconfigured"
827 073ca59e Iustin Pop
      else:
828 073ca59e Iustin Pop
        phy = ("configured as %s:%s %s:%s" %
829 25a915d0 Iustin Pop
               (self.physical_id[0], self.physical_id[1],
830 25a915d0 Iustin Pop
                self.physical_id[2], self.physical_id[3]))
831 073ca59e Iustin Pop
832 89f28b76 Iustin Pop
      val += ("hosts=%s/%d-%s/%d, port=%s, %s, " %
833 89f28b76 Iustin Pop
              (node_a, minor_a, node_b, minor_b, port, phy))
834 65a15336 Iustin Pop
      if self.children and self.children.count(None) == 0:
835 65a15336 Iustin Pop
        val += "backend=%s, metadev=%s" % (self.children[0], self.children[1])
836 65a15336 Iustin Pop
      else:
837 65a15336 Iustin Pop
        val += "no local storage"
838 65a15336 Iustin Pop
    else:
839 65a15336 Iustin Pop
      val = ("<Disk(type=%s, logical_id=%s, physical_id=%s, children=%s" %
840 65a15336 Iustin Pop
             (self.dev_type, self.logical_id, self.physical_id, self.children))
841 65a15336 Iustin Pop
    if self.iv_name is None:
842 65a15336 Iustin Pop
      val += ", not visible"
843 65a15336 Iustin Pop
    else:
844 65a15336 Iustin Pop
      val += ", visible as /dev/%s" % self.iv_name
845 fd965830 Iustin Pop
    if isinstance(self.size, int):
846 fd965830 Iustin Pop
      val += ", size=%dm)>" % self.size
847 fd965830 Iustin Pop
    else:
848 fd965830 Iustin Pop
      val += ", size='%s')>" % (self.size,)
849 65a15336 Iustin Pop
    return val
850 65a15336 Iustin Pop
851 332d0e37 Iustin Pop
  def Verify(self):
852 332d0e37 Iustin Pop
    """Checks that this disk is correctly configured.
853 332d0e37 Iustin Pop

854 332d0e37 Iustin Pop
    """
855 7c4d6c7b Michael Hanselmann
    all_errors = []
856 332d0e37 Iustin Pop
    if self.mode not in constants.DISK_ACCESS_SET:
857 7c4d6c7b Michael Hanselmann
      all_errors.append("Disk access mode '%s' is invalid" % (self.mode, ))
858 7c4d6c7b Michael Hanselmann
    return all_errors
859 332d0e37 Iustin Pop
860 90d726a8 Iustin Pop
  def UpgradeConfig(self):
861 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
862 90d726a8 Iustin Pop

863 90d726a8 Iustin Pop
    """
864 90d726a8 Iustin Pop
    if self.children:
865 90d726a8 Iustin Pop
      for child in self.children:
866 90d726a8 Iustin Pop
        child.UpgradeConfig()
867 bc5d0215 Andrea Spadaccini
868 bc5d0215 Andrea Spadaccini
    if not self.params:
869 bc5d0215 Andrea Spadaccini
      self.params = constants.DISK_LD_DEFAULTS[self.dev_type].copy()
870 bc5d0215 Andrea Spadaccini
    else:
871 bc5d0215 Andrea Spadaccini
      self.params = FillDict(constants.DISK_LD_DEFAULTS[self.dev_type],
872 bc5d0215 Andrea Spadaccini
                             self.params)
873 90d726a8 Iustin Pop
    # add here config upgrade for this disk
874 90d726a8 Iustin Pop
875 a8083063 Iustin Pop
876 918eb80b Agata Murawska
class InstancePolicy(ConfigObject):
877 918eb80b Agata Murawska
  """Config object representing instance policy limits dictionary."""
878 2cc673a3 Iustin Pop
  __slots__ = ["min", "max", "std", "disk_templates"]
879 918eb80b Agata Murawska
880 918eb80b Agata Murawska
  @classmethod
881 918eb80b Agata Murawska
  def CheckParameterSyntax(cls, ipolicy):
882 918eb80b Agata Murawska
    """ Check the instance policy for validity.
883 918eb80b Agata Murawska

884 918eb80b Agata Murawska
    """
885 918eb80b Agata Murawska
    for param in constants.ISPECS_PARAMETERS:
886 918eb80b Agata Murawska
      InstancePolicy.CheckISpecSyntax(ipolicy, param)
887 2cc673a3 Iustin Pop
    if constants.ISPECS_DTS in ipolicy:
888 2cc673a3 Iustin Pop
      InstancePolicy.CheckDiskTemplates(ipolicy[constants.ISPECS_DTS])
889 57dc299a Iustin Pop
    wrong_keys = frozenset(ipolicy.keys()) - constants.IPOLICY_ALL_KEYS
890 57dc299a Iustin Pop
    if wrong_keys:
891 57dc299a Iustin Pop
      raise errors.ConfigurationError("Invalid keys in ipolicy: %s" %
892 57dc299a Iustin Pop
                                      utils.CommaJoin(wrong_keys))
893 918eb80b Agata Murawska
894 918eb80b Agata Murawska
  @classmethod
895 918eb80b Agata Murawska
  def CheckISpecSyntax(cls, ipolicy, name):
896 918eb80b Agata Murawska
    """Check the instance policy for validity on a given key.
897 918eb80b Agata Murawska

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

901 918eb80b Agata Murawska
    @type ipolicy: dict
902 918eb80b Agata Murawska
    @param ipolicy: dictionary with min, max, std specs
903 918eb80b Agata Murawska
    @type name: string
904 918eb80b Agata Murawska
    @param name: what are the limits for
905 918eb80b Agata Murawska
    @raise errors.ConfigureError: when specs for given name are not valid
906 918eb80b Agata Murawska

907 918eb80b Agata Murawska
    """
908 4f725341 Agata Murawska
    min_v = ipolicy[constants.ISPECS_MIN].get(name, 0)
909 4f725341 Agata Murawska
    std_v = ipolicy[constants.ISPECS_STD].get(name, min_v)
910 4f725341 Agata Murawska
    max_v = ipolicy[constants.ISPECS_MAX].get(name, std_v)
911 918eb80b Agata Murawska
    err = ("Invalid specification of min/max/std values for %s: %s/%s/%s" %
912 918eb80b Agata Murawska
           (name,
913 4f725341 Agata Murawska
            ipolicy[constants.ISPECS_MIN].get(name, "-"),
914 4f725341 Agata Murawska
            ipolicy[constants.ISPECS_MAX].get(name, "-"),
915 4f725341 Agata Murawska
            ipolicy[constants.ISPECS_STD].get(name, "-")))
916 918eb80b Agata Murawska
    if min_v > std_v or std_v > max_v:
917 918eb80b Agata Murawska
      raise errors.ConfigurationError(err)
918 918eb80b Agata Murawska
919 2cc673a3 Iustin Pop
  @classmethod
920 2cc673a3 Iustin Pop
  def CheckDiskTemplates(cls, disk_templates):
921 2cc673a3 Iustin Pop
    """Checks the disk templates for validity.
922 2cc673a3 Iustin Pop

923 2cc673a3 Iustin Pop
    """
924 2cc673a3 Iustin Pop
    wrong = frozenset(disk_templates).difference(constants.DISK_TEMPLATES)
925 2cc673a3 Iustin Pop
    if wrong:
926 2cc673a3 Iustin Pop
      raise errors.ConfigurationError("Invalid disk template(s) %s" %
927 2cc673a3 Iustin Pop
                                      utils.CommaJoin(wrong))
928 2cc673a3 Iustin Pop
929 918eb80b Agata Murawska
930 ec29fe40 Iustin Pop
class Instance(TaggableObject):
931 a8083063 Iustin Pop
  """Config object representing an instance."""
932 154b9580 Balazs Lecz
  __slots__ = [
933 a8083063 Iustin Pop
    "name",
934 a8083063 Iustin Pop
    "primary_node",
935 a8083063 Iustin Pop
    "os",
936 e69d05fd Iustin Pop
    "hypervisor",
937 5bf7b5cf Iustin Pop
    "hvparams",
938 5bf7b5cf Iustin Pop
    "beparams",
939 1bdcbbab Iustin Pop
    "osparams",
940 9ca8a7c5 Agata Murawska
    "admin_state",
941 a8083063 Iustin Pop
    "nics",
942 a8083063 Iustin Pop
    "disks",
943 a8083063 Iustin Pop
    "disk_template",
944 58acb49d Alexander Schreiber
    "network_port",
945 be1fa613 Iustin Pop
    "serial_no",
946 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
947 a8083063 Iustin Pop
948 a8083063 Iustin Pop
  def _ComputeSecondaryNodes(self):
949 a8083063 Iustin Pop
    """Compute the list of secondary nodes.
950 a8083063 Iustin Pop

951 cfcc5c6d Iustin Pop
    This is a simple wrapper over _ComputeAllNodes.
952 cfcc5c6d Iustin Pop

953 cfcc5c6d Iustin Pop
    """
954 cfcc5c6d Iustin Pop
    all_nodes = set(self._ComputeAllNodes())
955 cfcc5c6d Iustin Pop
    all_nodes.discard(self.primary_node)
956 cfcc5c6d Iustin Pop
    return tuple(all_nodes)
957 cfcc5c6d Iustin Pop
958 cfcc5c6d Iustin Pop
  secondary_nodes = property(_ComputeSecondaryNodes, None, None,
959 cfcc5c6d Iustin Pop
                             "List of secondary nodes")
960 cfcc5c6d Iustin Pop
961 cfcc5c6d Iustin Pop
  def _ComputeAllNodes(self):
962 cfcc5c6d Iustin Pop
    """Compute the list of all nodes.
963 cfcc5c6d Iustin Pop

964 a8083063 Iustin Pop
    Since the data is already there (in the drbd disks), keeping it as
965 a8083063 Iustin Pop
    a separate normal attribute is redundant and if not properly
966 a8083063 Iustin Pop
    synchronised can cause problems. Thus it's better to compute it
967 a8083063 Iustin Pop
    dynamically.
968 a8083063 Iustin Pop

969 a8083063 Iustin Pop
    """
970 cfcc5c6d Iustin Pop
    def _Helper(nodes, device):
971 cfcc5c6d Iustin Pop
      """Recursively computes nodes given a top device."""
972 a1f445d3 Iustin Pop
      if device.dev_type in constants.LDS_DRBD:
973 cfcc5c6d Iustin Pop
        nodea, nodeb = device.logical_id[:2]
974 cfcc5c6d Iustin Pop
        nodes.add(nodea)
975 cfcc5c6d Iustin Pop
        nodes.add(nodeb)
976 a8083063 Iustin Pop
      if device.children:
977 a8083063 Iustin Pop
        for child in device.children:
978 cfcc5c6d Iustin Pop
          _Helper(nodes, child)
979 a8083063 Iustin Pop
980 cfcc5c6d Iustin Pop
    all_nodes = set()
981 99c7b2a1 Iustin Pop
    all_nodes.add(self.primary_node)
982 a8083063 Iustin Pop
    for device in self.disks:
983 cfcc5c6d Iustin Pop
      _Helper(all_nodes, device)
984 cfcc5c6d Iustin Pop
    return tuple(all_nodes)
985 a8083063 Iustin Pop
986 cfcc5c6d Iustin Pop
  all_nodes = property(_ComputeAllNodes, None, None,
987 cfcc5c6d Iustin Pop
                       "List of all nodes of the instance")
988 a8083063 Iustin Pop
989 a8083063 Iustin Pop
  def MapLVsByNode(self, lvmap=None, devs=None, node=None):
990 a8083063 Iustin Pop
    """Provide a mapping of nodes to LVs this instance owns.
991 a8083063 Iustin Pop

992 c41eea6e Iustin Pop
    This function figures out what logical volumes should belong on
993 c41eea6e Iustin Pop
    which nodes, recursing through a device tree.
994 a8083063 Iustin Pop

995 c41eea6e Iustin Pop
    @param lvmap: optional dictionary to receive the
996 c41eea6e Iustin Pop
        'node' : ['lv', ...] data.
997 a8083063 Iustin Pop

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

1003 a8083063 Iustin Pop
    """
1004 a8083063 Iustin Pop
    if node == None:
1005 a8083063 Iustin Pop
      node = self.primary_node
1006 a8083063 Iustin Pop
1007 a8083063 Iustin Pop
    if lvmap is None:
1008 e687ec01 Michael Hanselmann
      lvmap = {
1009 e687ec01 Michael Hanselmann
        node: [],
1010 e687ec01 Michael Hanselmann
        }
1011 a8083063 Iustin Pop
      ret = lvmap
1012 a8083063 Iustin Pop
    else:
1013 a8083063 Iustin Pop
      if not node in lvmap:
1014 a8083063 Iustin Pop
        lvmap[node] = []
1015 a8083063 Iustin Pop
      ret = None
1016 a8083063 Iustin Pop
1017 a8083063 Iustin Pop
    if not devs:
1018 a8083063 Iustin Pop
      devs = self.disks
1019 a8083063 Iustin Pop
1020 a8083063 Iustin Pop
    for dev in devs:
1021 fe96220b Iustin Pop
      if dev.dev_type == constants.LD_LV:
1022 e687ec01 Michael Hanselmann
        lvmap[node].append(dev.logical_id[0] + "/" + dev.logical_id[1])
1023 a8083063 Iustin Pop
1024 a1f445d3 Iustin Pop
      elif dev.dev_type in constants.LDS_DRBD:
1025 a8083063 Iustin Pop
        if dev.children:
1026 a8083063 Iustin Pop
          self.MapLVsByNode(lvmap, dev.children, dev.logical_id[0])
1027 a8083063 Iustin Pop
          self.MapLVsByNode(lvmap, dev.children, dev.logical_id[1])
1028 a8083063 Iustin Pop
1029 a8083063 Iustin Pop
      elif dev.children:
1030 a8083063 Iustin Pop
        self.MapLVsByNode(lvmap, dev.children, node)
1031 a8083063 Iustin Pop
1032 a8083063 Iustin Pop
    return ret
1033 a8083063 Iustin Pop
1034 ad24e046 Iustin Pop
  def FindDisk(self, idx):
1035 ad24e046 Iustin Pop
    """Find a disk given having a specified index.
1036 644eeef9 Iustin Pop

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

1039 ad24e046 Iustin Pop
    @type idx: int
1040 ad24e046 Iustin Pop
    @param idx: the disk index
1041 ad24e046 Iustin Pop
    @rtype: L{Disk}
1042 ad24e046 Iustin Pop
    @return: the corresponding disk
1043 ad24e046 Iustin Pop
    @raise errors.OpPrereqError: when the given index is not valid
1044 644eeef9 Iustin Pop

1045 ad24e046 Iustin Pop
    """
1046 ad24e046 Iustin Pop
    try:
1047 ad24e046 Iustin Pop
      idx = int(idx)
1048 ad24e046 Iustin Pop
      return self.disks[idx]
1049 691744c4 Iustin Pop
    except (TypeError, ValueError), err:
1050 debac808 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index: '%s'" % str(err),
1051 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
1052 ad24e046 Iustin Pop
    except IndexError:
1053 ad24e046 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index: %d (instace has disks"
1054 daa55b04 Michael Hanselmann
                                 " 0 to %d" % (idx, len(self.disks) - 1),
1055 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
1056 644eeef9 Iustin Pop
1057 ff9c047c Iustin Pop
  def ToDict(self):
1058 ff9c047c Iustin Pop
    """Instance-specific conversion to standard python types.
1059 ff9c047c Iustin Pop

1060 ff9c047c Iustin Pop
    This replaces the children lists of objects with lists of standard
1061 ff9c047c Iustin Pop
    python types.
1062 ff9c047c Iustin Pop

1063 ff9c047c Iustin Pop
    """
1064 ff9c047c Iustin Pop
    bo = super(Instance, self).ToDict()
1065 ff9c047c Iustin Pop
1066 ff9c047c Iustin Pop
    for attr in "nics", "disks":
1067 ff9c047c Iustin Pop
      alist = bo.get(attr, None)
1068 ff9c047c Iustin Pop
      if alist:
1069 ff9c047c Iustin Pop
        nlist = self._ContainerToDicts(alist)
1070 ff9c047c Iustin Pop
      else:
1071 ff9c047c Iustin Pop
        nlist = []
1072 ff9c047c Iustin Pop
      bo[attr] = nlist
1073 ff9c047c Iustin Pop
    return bo
1074 ff9c047c Iustin Pop
1075 ff9c047c Iustin Pop
  @classmethod
1076 ff9c047c Iustin Pop
  def FromDict(cls, val):
1077 ff9c047c Iustin Pop
    """Custom function for instances.
1078 ff9c047c Iustin Pop

1079 ff9c047c Iustin Pop
    """
1080 9ca8a7c5 Agata Murawska
    if "admin_state" not in val:
1081 9ca8a7c5 Agata Murawska
      if val.get("admin_up", False):
1082 9ca8a7c5 Agata Murawska
        val["admin_state"] = constants.ADMINST_UP
1083 9ca8a7c5 Agata Murawska
      else:
1084 9ca8a7c5 Agata Murawska
        val["admin_state"] = constants.ADMINST_DOWN
1085 9ca8a7c5 Agata Murawska
    if "admin_up" in val:
1086 9ca8a7c5 Agata Murawska
      del val["admin_up"]
1087 ff9c047c Iustin Pop
    obj = super(Instance, cls).FromDict(val)
1088 ff9c047c Iustin Pop
    obj.nics = cls._ContainerFromDicts(obj.nics, list, NIC)
1089 ff9c047c Iustin Pop
    obj.disks = cls._ContainerFromDicts(obj.disks, list, Disk)
1090 ff9c047c Iustin Pop
    return obj
1091 ff9c047c Iustin Pop
1092 90d726a8 Iustin Pop
  def UpgradeConfig(self):
1093 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
1094 90d726a8 Iustin Pop

1095 90d726a8 Iustin Pop
    """
1096 90d726a8 Iustin Pop
    for nic in self.nics:
1097 90d726a8 Iustin Pop
      nic.UpgradeConfig()
1098 90d726a8 Iustin Pop
    for disk in self.disks:
1099 90d726a8 Iustin Pop
      disk.UpgradeConfig()
1100 7736a5f2 Iustin Pop
    if self.hvparams:
1101 7736a5f2 Iustin Pop
      for key in constants.HVC_GLOBALS:
1102 7736a5f2 Iustin Pop
        try:
1103 7736a5f2 Iustin Pop
          del self.hvparams[key]
1104 7736a5f2 Iustin Pop
        except KeyError:
1105 7736a5f2 Iustin Pop
          pass
1106 1bdcbbab Iustin Pop
    if self.osparams is None:
1107 1bdcbbab Iustin Pop
      self.osparams = {}
1108 8c72ab2b Guido Trotter
    UpgradeBeParams(self.beparams)
1109 90d726a8 Iustin Pop
1110 a8083063 Iustin Pop
1111 a8083063 Iustin Pop
class OS(ConfigObject):
1112 b41b3516 Iustin Pop
  """Config object representing an operating system.
1113 b41b3516 Iustin Pop

1114 b41b3516 Iustin Pop
  @type supported_parameters: list
1115 b41b3516 Iustin Pop
  @ivar supported_parameters: a list of tuples, name and description,
1116 b41b3516 Iustin Pop
      containing the supported parameters by this OS
1117 b41b3516 Iustin Pop

1118 870dc44c Iustin Pop
  @type VARIANT_DELIM: string
1119 870dc44c Iustin Pop
  @cvar VARIANT_DELIM: the variant delimiter
1120 870dc44c Iustin Pop

1121 b41b3516 Iustin Pop
  """
1122 a8083063 Iustin Pop
  __slots__ = [
1123 a8083063 Iustin Pop
    "name",
1124 a8083063 Iustin Pop
    "path",
1125 082a7f91 Guido Trotter
    "api_versions",
1126 a8083063 Iustin Pop
    "create_script",
1127 a8083063 Iustin Pop
    "export_script",
1128 386b57af Iustin Pop
    "import_script",
1129 386b57af Iustin Pop
    "rename_script",
1130 b41b3516 Iustin Pop
    "verify_script",
1131 6d79896b Guido Trotter
    "supported_variants",
1132 b41b3516 Iustin Pop
    "supported_parameters",
1133 a8083063 Iustin Pop
    ]
1134 a8083063 Iustin Pop
1135 870dc44c Iustin Pop
  VARIANT_DELIM = "+"
1136 870dc44c Iustin Pop
1137 870dc44c Iustin Pop
  @classmethod
1138 870dc44c Iustin Pop
  def SplitNameVariant(cls, name):
1139 870dc44c Iustin Pop
    """Splits the name into the proper name and variant.
1140 870dc44c Iustin Pop

1141 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
1142 870dc44c Iustin Pop
    @rtype: list
1143 870dc44c Iustin Pop
    @return: a list of two elements; if the original name didn't
1144 870dc44c Iustin Pop
        contain a variant, it's returned as an empty string
1145 870dc44c Iustin Pop

1146 870dc44c Iustin Pop
    """
1147 870dc44c Iustin Pop
    nv = name.split(cls.VARIANT_DELIM, 1)
1148 870dc44c Iustin Pop
    if len(nv) == 1:
1149 870dc44c Iustin Pop
      nv.append("")
1150 870dc44c Iustin Pop
    return nv
1151 870dc44c Iustin Pop
1152 870dc44c Iustin Pop
  @classmethod
1153 870dc44c Iustin Pop
  def GetName(cls, name):
1154 870dc44c Iustin Pop
    """Returns the proper name of the os (without the variant).
1155 870dc44c Iustin Pop

1156 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
1157 870dc44c Iustin Pop

1158 870dc44c Iustin Pop
    """
1159 870dc44c Iustin Pop
    return cls.SplitNameVariant(name)[0]
1160 870dc44c Iustin Pop
1161 870dc44c Iustin Pop
  @classmethod
1162 870dc44c Iustin Pop
  def GetVariant(cls, name):
1163 870dc44c Iustin Pop
    """Returns the variant the os (without the base name).
1164 870dc44c Iustin Pop

1165 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
1166 870dc44c Iustin Pop

1167 870dc44c Iustin Pop
    """
1168 870dc44c Iustin Pop
    return cls.SplitNameVariant(name)[1]
1169 870dc44c Iustin Pop
1170 7c0d6283 Michael Hanselmann
1171 5f06ce5e Michael Hanselmann
class NodeHvState(ConfigObject):
1172 5f06ce5e Michael Hanselmann
  """Hypvervisor state on a node.
1173 5f06ce5e Michael Hanselmann

1174 5f06ce5e Michael Hanselmann
  @ivar mem_total: Total amount of memory
1175 5f06ce5e Michael Hanselmann
  @ivar mem_node: Memory used by, or reserved for, the node itself (not always
1176 5f06ce5e Michael Hanselmann
    available)
1177 5f06ce5e Michael Hanselmann
  @ivar mem_hv: Memory used by hypervisor or lost due to instance allocation
1178 5f06ce5e Michael Hanselmann
    rounding
1179 5f06ce5e Michael Hanselmann
  @ivar mem_inst: Memory used by instances living on node
1180 5f06ce5e Michael Hanselmann
  @ivar cpu_total: Total node CPU core count
1181 5f06ce5e Michael Hanselmann
  @ivar cpu_node: Number of CPU cores reserved for the node itself
1182 5f06ce5e Michael Hanselmann

1183 5f06ce5e Michael Hanselmann
  """
1184 5f06ce5e Michael Hanselmann
  __slots__ = [
1185 5f06ce5e Michael Hanselmann
    "mem_total",
1186 5f06ce5e Michael Hanselmann
    "mem_node",
1187 5f06ce5e Michael Hanselmann
    "mem_hv",
1188 5f06ce5e Michael Hanselmann
    "mem_inst",
1189 5f06ce5e Michael Hanselmann
    "cpu_total",
1190 5f06ce5e Michael Hanselmann
    "cpu_node",
1191 5f06ce5e Michael Hanselmann
    ] + _TIMESTAMPS
1192 5f06ce5e Michael Hanselmann
1193 5f06ce5e Michael Hanselmann
1194 5f06ce5e Michael Hanselmann
class NodeDiskState(ConfigObject):
1195 5f06ce5e Michael Hanselmann
  """Disk state on a node.
1196 5f06ce5e Michael Hanselmann

1197 5f06ce5e Michael Hanselmann
  """
1198 5f06ce5e Michael Hanselmann
  __slots__ = [
1199 5f06ce5e Michael Hanselmann
    "total",
1200 5f06ce5e Michael Hanselmann
    "reserved",
1201 5f06ce5e Michael Hanselmann
    "overhead",
1202 5f06ce5e Michael Hanselmann
    ] + _TIMESTAMPS
1203 5f06ce5e Michael Hanselmann
1204 5f06ce5e Michael Hanselmann
1205 ec29fe40 Iustin Pop
class Node(TaggableObject):
1206 634d30f4 Michael Hanselmann
  """Config object representing a node.
1207 634d30f4 Michael Hanselmann

1208 634d30f4 Michael Hanselmann
  @ivar hv_state: Hypervisor state (e.g. number of CPUs)
1209 634d30f4 Michael Hanselmann
  @ivar hv_state_static: Hypervisor state overriden by user
1210 634d30f4 Michael Hanselmann
  @ivar disk_state: Disk state (e.g. free space)
1211 634d30f4 Michael Hanselmann
  @ivar disk_state_static: Disk state overriden by user
1212 634d30f4 Michael Hanselmann

1213 634d30f4 Michael Hanselmann
  """
1214 154b9580 Balazs Lecz
  __slots__ = [
1215 ec29fe40 Iustin Pop
    "name",
1216 ec29fe40 Iustin Pop
    "primary_ip",
1217 ec29fe40 Iustin Pop
    "secondary_ip",
1218 be1fa613 Iustin Pop
    "serial_no",
1219 8b8b8b81 Iustin Pop
    "master_candidate",
1220 fc0fe88c Iustin Pop
    "offline",
1221 af64c0ea Iustin Pop
    "drained",
1222 f936c153 Iustin Pop
    "group",
1223 490acd18 Iustin Pop
    "master_capable",
1224 490acd18 Iustin Pop
    "vm_capable",
1225 095e71aa Renรฉ Nussbaumer
    "ndparams",
1226 25124d4a Renรฉ Nussbaumer
    "powered",
1227 5b49ed09 Renรฉ Nussbaumer
    "hv_state",
1228 634d30f4 Michael Hanselmann
    "hv_state_static",
1229 5b49ed09 Renรฉ Nussbaumer
    "disk_state",
1230 634d30f4 Michael Hanselmann
    "disk_state_static",
1231 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
1232 a8083063 Iustin Pop
1233 490acd18 Iustin Pop
  def UpgradeConfig(self):
1234 490acd18 Iustin Pop
    """Fill defaults for missing configuration values.
1235 490acd18 Iustin Pop

1236 490acd18 Iustin Pop
    """
1237 b459a848 Andrea Spadaccini
    # pylint: disable=E0203
1238 490acd18 Iustin Pop
    # because these are "defined" via slots, not manually
1239 490acd18 Iustin Pop
    if self.master_capable is None:
1240 490acd18 Iustin Pop
      self.master_capable = True
1241 490acd18 Iustin Pop
1242 490acd18 Iustin Pop
    if self.vm_capable is None:
1243 490acd18 Iustin Pop
      self.vm_capable = True
1244 490acd18 Iustin Pop
1245 095e71aa Renรฉ Nussbaumer
    if self.ndparams is None:
1246 095e71aa Renรฉ Nussbaumer
      self.ndparams = {}
1247 095e71aa Renรฉ Nussbaumer
1248 25124d4a Renรฉ Nussbaumer
    if self.powered is None:
1249 25124d4a Renรฉ Nussbaumer
      self.powered = True
1250 25124d4a Renรฉ Nussbaumer
1251 5f06ce5e Michael Hanselmann
  def ToDict(self):
1252 5f06ce5e Michael Hanselmann
    """Custom function for serializing.
1253 5f06ce5e Michael Hanselmann

1254 5f06ce5e Michael Hanselmann
    """
1255 5f06ce5e Michael Hanselmann
    data = super(Node, self).ToDict()
1256 5f06ce5e Michael Hanselmann
1257 5f06ce5e Michael Hanselmann
    hv_state = data.get("hv_state", None)
1258 5f06ce5e Michael Hanselmann
    if hv_state is not None:
1259 5f06ce5e Michael Hanselmann
      data["hv_state"] = self._ContainerToDicts(hv_state)
1260 5f06ce5e Michael Hanselmann
1261 5f06ce5e Michael Hanselmann
    disk_state = data.get("disk_state", None)
1262 5f06ce5e Michael Hanselmann
    if disk_state is not None:
1263 5f06ce5e Michael Hanselmann
      data["disk_state"] = \
1264 5f06ce5e Michael Hanselmann
        dict((key, self._ContainerToDicts(value))
1265 5f06ce5e Michael Hanselmann
             for (key, value) in disk_state.items())
1266 5f06ce5e Michael Hanselmann
1267 5f06ce5e Michael Hanselmann
    return data
1268 5f06ce5e Michael Hanselmann
1269 5f06ce5e Michael Hanselmann
  @classmethod
1270 5f06ce5e Michael Hanselmann
  def FromDict(cls, val):
1271 5f06ce5e Michael Hanselmann
    """Custom function for deserializing.
1272 5f06ce5e Michael Hanselmann

1273 5f06ce5e Michael Hanselmann
    """
1274 5f06ce5e Michael Hanselmann
    obj = super(Node, cls).FromDict(val)
1275 5f06ce5e Michael Hanselmann
1276 5f06ce5e Michael Hanselmann
    if obj.hv_state is not None:
1277 5f06ce5e Michael Hanselmann
      obj.hv_state = cls._ContainerFromDicts(obj.hv_state, dict, NodeHvState)
1278 5f06ce5e Michael Hanselmann
1279 5f06ce5e Michael Hanselmann
    if obj.disk_state is not None:
1280 5f06ce5e Michael Hanselmann
      obj.disk_state = \
1281 5f06ce5e Michael Hanselmann
        dict((key, cls._ContainerFromDicts(value, dict, NodeDiskState))
1282 5f06ce5e Michael Hanselmann
             for (key, value) in obj.disk_state.items())
1283 5f06ce5e Michael Hanselmann
1284 5f06ce5e Michael Hanselmann
    return obj
1285 5f06ce5e Michael Hanselmann
1286 a8083063 Iustin Pop
1287 1ffd2673 Michael Hanselmann
class NodeGroup(TaggableObject):
1288 24a3707f Guido Trotter
  """Config object representing a node group."""
1289 24a3707f Guido Trotter
  __slots__ = [
1290 24a3707f Guido Trotter
    "name",
1291 24a3707f Guido Trotter
    "members",
1292 095e71aa Renรฉ Nussbaumer
    "ndparams",
1293 bc5d0215 Andrea Spadaccini
    "diskparams",
1294 81e3ab4f Agata Murawska
    "ipolicy",
1295 e11a1b77 Adeodato Simo
    "serial_no",
1296 a8282327 Renรฉ Nussbaumer
    "hv_state_static",
1297 a8282327 Renรฉ Nussbaumer
    "disk_state_static",
1298 90e99856 Adeodato Simo
    "alloc_policy",
1299 24a3707f Guido Trotter
    ] + _TIMESTAMPS + _UUID
1300 24a3707f Guido Trotter
1301 24a3707f Guido Trotter
  def ToDict(self):
1302 24a3707f Guido Trotter
    """Custom function for nodegroup.
1303 24a3707f Guido Trotter

1304 c60abd62 Guido Trotter
    This discards the members object, which gets recalculated and is only kept
1305 c60abd62 Guido Trotter
    in memory.
1306 24a3707f Guido Trotter

1307 24a3707f Guido Trotter
    """
1308 24a3707f Guido Trotter
    mydict = super(NodeGroup, self).ToDict()
1309 24a3707f Guido Trotter
    del mydict["members"]
1310 24a3707f Guido Trotter
    return mydict
1311 24a3707f Guido Trotter
1312 24a3707f Guido Trotter
  @classmethod
1313 24a3707f Guido Trotter
  def FromDict(cls, val):
1314 24a3707f Guido Trotter
    """Custom function for nodegroup.
1315 24a3707f Guido Trotter

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

1318 24a3707f Guido Trotter
    """
1319 24a3707f Guido Trotter
    obj = super(NodeGroup, cls).FromDict(val)
1320 24a3707f Guido Trotter
    obj.members = []
1321 24a3707f Guido Trotter
    return obj
1322 24a3707f Guido Trotter
1323 095e71aa Renรฉ Nussbaumer
  def UpgradeConfig(self):
1324 095e71aa Renรฉ Nussbaumer
    """Fill defaults for missing configuration values.
1325 095e71aa Renรฉ Nussbaumer

1326 095e71aa Renรฉ Nussbaumer
    """
1327 095e71aa Renรฉ Nussbaumer
    if self.ndparams is None:
1328 095e71aa Renรฉ Nussbaumer
      self.ndparams = {}
1329 095e71aa Renรฉ Nussbaumer
1330 e11a1b77 Adeodato Simo
    if self.serial_no is None:
1331 e11a1b77 Adeodato Simo
      self.serial_no = 1
1332 e11a1b77 Adeodato Simo
1333 90e99856 Adeodato Simo
    if self.alloc_policy is None:
1334 90e99856 Adeodato Simo
      self.alloc_policy = constants.ALLOC_POLICY_PREFERRED
1335 90e99856 Adeodato Simo
1336 4b97458c Iustin Pop
    # We only update mtime, and not ctime, since we would not be able
1337 4b97458c Iustin Pop
    # to provide a correct value for creation time.
1338 e11a1b77 Adeodato Simo
    if self.mtime is None:
1339 e11a1b77 Adeodato Simo
      self.mtime = time.time()
1340 e11a1b77 Adeodato Simo
1341 bc5d0215 Andrea Spadaccini
    self.diskparams = UpgradeDiskParams(self.diskparams)
1342 81e3ab4f Agata Murawska
    if self.ipolicy is None:
1343 81e3ab4f Agata Murawska
      self.ipolicy = MakeEmptyIPolicy()
1344 bc5d0215 Andrea Spadaccini
1345 095e71aa Renรฉ Nussbaumer
  def FillND(self, node):
1346 ce523de1 Michael Hanselmann
    """Return filled out ndparams for L{objects.Node}
1347 095e71aa Renรฉ Nussbaumer

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

1352 095e71aa Renรฉ Nussbaumer
    """
1353 095e71aa Renรฉ Nussbaumer
    return self.SimpleFillND(node.ndparams)
1354 095e71aa Renรฉ Nussbaumer
1355 095e71aa Renรฉ Nussbaumer
  def SimpleFillND(self, ndparams):
1356 095e71aa Renรฉ Nussbaumer
    """Fill a given ndparams dict with defaults.
1357 095e71aa Renรฉ Nussbaumer

1358 095e71aa Renรฉ Nussbaumer
    @type ndparams: dict
1359 095e71aa Renรฉ Nussbaumer
    @param ndparams: the dict to fill
1360 095e71aa Renรฉ Nussbaumer
    @rtype: dict
1361 095e71aa Renรฉ Nussbaumer
    @return: a copy of the passed in ndparams with missing keys filled
1362 e6e88de6 Adeodato Simo
        from the node group defaults
1363 095e71aa Renรฉ Nussbaumer

1364 095e71aa Renรฉ Nussbaumer
    """
1365 095e71aa Renรฉ Nussbaumer
    return FillDict(self.ndparams, ndparams)
1366 095e71aa Renรฉ Nussbaumer
1367 24a3707f Guido Trotter
1368 ec29fe40 Iustin Pop
class Cluster(TaggableObject):
1369 a8083063 Iustin Pop
  """Config object representing the cluster."""
1370 154b9580 Balazs Lecz
  __slots__ = [
1371 a8083063 Iustin Pop
    "serial_no",
1372 a8083063 Iustin Pop
    "rsahostkeypub",
1373 a8083063 Iustin Pop
    "highest_used_port",
1374 b2fddf63 Iustin Pop
    "tcpudp_port_pool",
1375 a8083063 Iustin Pop
    "mac_prefix",
1376 a8083063 Iustin Pop
    "volume_group_name",
1377 999b183c Iustin Pop
    "reserved_lvs",
1378 9e33896b Luca Bigliardi
    "drbd_usermode_helper",
1379 a8083063 Iustin Pop
    "default_bridge",
1380 02691904 Alexander Schreiber
    "default_hypervisor",
1381 f6bd6e98 Michael Hanselmann
    "master_node",
1382 f6bd6e98 Michael Hanselmann
    "master_ip",
1383 f6bd6e98 Michael Hanselmann
    "master_netdev",
1384 5a8648eb Andrea Spadaccini
    "master_netmask",
1385 33be7576 Andrea Spadaccini
    "use_external_mip_script",
1386 f6bd6e98 Michael Hanselmann
    "cluster_name",
1387 f6bd6e98 Michael Hanselmann
    "file_storage_dir",
1388 4b97f902 Apollon Oikonomopoulos
    "shared_file_storage_dir",
1389 e69d05fd Iustin Pop
    "enabled_hypervisors",
1390 5bf7b5cf Iustin Pop
    "hvparams",
1391 918eb80b Agata Murawska
    "ipolicy",
1392 17463d22 Renรฉ Nussbaumer
    "os_hvp",
1393 5bf7b5cf Iustin Pop
    "beparams",
1394 1bdcbbab Iustin Pop
    "osparams",
1395 c8fcde47 Guido Trotter
    "nicparams",
1396 095e71aa Renรฉ Nussbaumer
    "ndparams",
1397 bc5d0215 Andrea Spadaccini
    "diskparams",
1398 4b7735f9 Iustin Pop
    "candidate_pool_size",
1399 b86a6bcd Guido Trotter
    "modify_etc_hosts",
1400 b989b9d9 Ken Wehr
    "modify_ssh_setup",
1401 3953242f Iustin Pop
    "maintain_node_health",
1402 4437d889 Balazs Lecz
    "uid_pool",
1403 bf4af505 Apollon Oikonomopoulos
    "default_iallocator",
1404 87b2cd45 Iustin Pop
    "hidden_os",
1405 87b2cd45 Iustin Pop
    "blacklisted_os",
1406 2f20d07b Manuel Franceschini
    "primary_ip_family",
1407 3d914585 Renรฉ Nussbaumer
    "prealloc_wipe_disks",
1408 2da9f556 Renรฉ Nussbaumer
    "hv_state_static",
1409 2da9f556 Renรฉ Nussbaumer
    "disk_state_static",
1410 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
1411 a8083063 Iustin Pop
1412 b86a6bcd Guido Trotter
  def UpgradeConfig(self):
1413 b86a6bcd Guido Trotter
    """Fill defaults for missing configuration values.
1414 b86a6bcd Guido Trotter

1415 b86a6bcd Guido Trotter
    """
1416 b459a848 Andrea Spadaccini
    # pylint: disable=E0203
1417 fe267188 Iustin Pop
    # because these are "defined" via slots, not manually
1418 c1b42c18 Guido Trotter
    if self.hvparams is None:
1419 c1b42c18 Guido Trotter
      self.hvparams = constants.HVC_DEFAULTS
1420 c1b42c18 Guido Trotter
    else:
1421 c1b42c18 Guido Trotter
      for hypervisor in self.hvparams:
1422 abe609b2 Guido Trotter
        self.hvparams[hypervisor] = FillDict(
1423 c1b42c18 Guido Trotter
            constants.HVC_DEFAULTS[hypervisor], self.hvparams[hypervisor])
1424 c1b42c18 Guido Trotter
1425 17463d22 Renรฉ Nussbaumer
    if self.os_hvp is None:
1426 17463d22 Renรฉ Nussbaumer
      self.os_hvp = {}
1427 17463d22 Renรฉ Nussbaumer
1428 1bdcbbab Iustin Pop
    # osparams added before 2.2
1429 1bdcbbab Iustin Pop
    if self.osparams is None:
1430 1bdcbbab Iustin Pop
      self.osparams = {}
1431 1bdcbbab Iustin Pop
1432 095e71aa Renรฉ Nussbaumer
    if self.ndparams is None:
1433 095e71aa Renรฉ Nussbaumer
      self.ndparams = constants.NDC_DEFAULTS
1434 095e71aa Renรฉ Nussbaumer
1435 6e34b628 Guido Trotter
    self.beparams = UpgradeGroupedParams(self.beparams,
1436 6e34b628 Guido Trotter
                                         constants.BEC_DEFAULTS)
1437 8c72ab2b Guido Trotter
    for beparams_group in self.beparams:
1438 8c72ab2b Guido Trotter
      UpgradeBeParams(self.beparams[beparams_group])
1439 8c72ab2b Guido Trotter
1440 c8fcde47 Guido Trotter
    migrate_default_bridge = not self.nicparams
1441 c8fcde47 Guido Trotter
    self.nicparams = UpgradeGroupedParams(self.nicparams,
1442 c8fcde47 Guido Trotter
                                          constants.NICC_DEFAULTS)
1443 c8fcde47 Guido Trotter
    if migrate_default_bridge:
1444 c8fcde47 Guido Trotter
      self.nicparams[constants.PP_DEFAULT][constants.NIC_LINK] = \
1445 c8fcde47 Guido Trotter
        self.default_bridge
1446 c1b42c18 Guido Trotter
1447 b86a6bcd Guido Trotter
    if self.modify_etc_hosts is None:
1448 b86a6bcd Guido Trotter
      self.modify_etc_hosts = True
1449 b86a6bcd Guido Trotter
1450 b989b9d9 Ken Wehr
    if self.modify_ssh_setup is None:
1451 b989b9d9 Ken Wehr
      self.modify_ssh_setup = True
1452 b989b9d9 Ken Wehr
1453 73f1d185 Stephen Shirley
    # default_bridge is no longer used in 2.1. The slot is left there to
1454 90d118fd Guido Trotter
    # support auto-upgrading. It can be removed once we decide to deprecate
1455 90d118fd Guido Trotter
    # upgrading straight from 2.0.
1456 9b31ca85 Guido Trotter
    if self.default_bridge is not None:
1457 9b31ca85 Guido Trotter
      self.default_bridge = None
1458 9b31ca85 Guido Trotter
1459 90d118fd Guido Trotter
    # default_hypervisor is just the first enabled one in 2.1. This slot and
1460 90d118fd Guido Trotter
    # code can be removed once upgrading straight from 2.0 is deprecated.
1461 066f465d Guido Trotter
    if self.default_hypervisor is not None:
1462 016d04b3 Michael Hanselmann
      self.enabled_hypervisors = ([self.default_hypervisor] +
1463 066f465d Guido Trotter
        [hvname for hvname in self.enabled_hypervisors
1464 016d04b3 Michael Hanselmann
         if hvname != self.default_hypervisor])
1465 066f465d Guido Trotter
      self.default_hypervisor = None
1466 066f465d Guido Trotter
1467 3953242f Iustin Pop
    # maintain_node_health added after 2.1.1
1468 3953242f Iustin Pop
    if self.maintain_node_health is None:
1469 3953242f Iustin Pop
      self.maintain_node_health = False
1470 3953242f Iustin Pop
1471 4437d889 Balazs Lecz
    if self.uid_pool is None:
1472 4437d889 Balazs Lecz
      self.uid_pool = []
1473 4437d889 Balazs Lecz
1474 bf4af505 Apollon Oikonomopoulos
    if self.default_iallocator is None:
1475 bf4af505 Apollon Oikonomopoulos
      self.default_iallocator = ""
1476 bf4af505 Apollon Oikonomopoulos
1477 999b183c Iustin Pop
    # reserved_lvs added before 2.2
1478 999b183c Iustin Pop
    if self.reserved_lvs is None:
1479 999b183c Iustin Pop
      self.reserved_lvs = []
1480 999b183c Iustin Pop
1481 546b1111 Iustin Pop
    # hidden and blacklisted operating systems added before 2.2.1
1482 87b2cd45 Iustin Pop
    if self.hidden_os is None:
1483 87b2cd45 Iustin Pop
      self.hidden_os = []
1484 546b1111 Iustin Pop
1485 87b2cd45 Iustin Pop
    if self.blacklisted_os is None:
1486 87b2cd45 Iustin Pop
      self.blacklisted_os = []
1487 546b1111 Iustin Pop
1488 f4c9af7a Guido Trotter
    # primary_ip_family added before 2.3
1489 f4c9af7a Guido Trotter
    if self.primary_ip_family is None:
1490 f4c9af7a Guido Trotter
      self.primary_ip_family = AF_INET
1491 f4c9af7a Guido Trotter
1492 0007f3ab Andrea Spadaccini
    if self.master_netmask is None:
1493 0007f3ab Andrea Spadaccini
      ipcls = netutils.IPAddress.GetClassFromIpFamily(self.primary_ip_family)
1494 0007f3ab Andrea Spadaccini
      self.master_netmask = ipcls.iplen
1495 0007f3ab Andrea Spadaccini
1496 3d914585 Renรฉ Nussbaumer
    if self.prealloc_wipe_disks is None:
1497 3d914585 Renรฉ Nussbaumer
      self.prealloc_wipe_disks = False
1498 3d914585 Renรฉ Nussbaumer
1499 e8f472d1 Iustin Pop
    # shared_file_storage_dir added before 2.5
1500 e8f472d1 Iustin Pop
    if self.shared_file_storage_dir is None:
1501 e8f472d1 Iustin Pop
      self.shared_file_storage_dir = ""
1502 e8f472d1 Iustin Pop
1503 33be7576 Andrea Spadaccini
    if self.use_external_mip_script is None:
1504 33be7576 Andrea Spadaccini
      self.use_external_mip_script = False
1505 33be7576 Andrea Spadaccini
1506 bc5d0215 Andrea Spadaccini
    self.diskparams = UpgradeDiskParams(self.diskparams)
1507 bc5d0215 Andrea Spadaccini
1508 918eb80b Agata Murawska
    # instance policy added before 2.6
1509 918eb80b Agata Murawska
    if self.ipolicy is None:
1510 2cc673a3 Iustin Pop
      self.ipolicy = FillIPolicy(constants.IPOLICY_DEFAULTS, {})
1511 918eb80b Agata Murawska
1512 0fbedb7a Michael Hanselmann
  @property
1513 0fbedb7a Michael Hanselmann
  def primary_hypervisor(self):
1514 0fbedb7a Michael Hanselmann
    """The first hypervisor is the primary.
1515 0fbedb7a Michael Hanselmann

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

1518 0fbedb7a Michael Hanselmann
    """
1519 0fbedb7a Michael Hanselmann
    return self.enabled_hypervisors[0]
1520 0fbedb7a Michael Hanselmann
1521 319856a9 Michael Hanselmann
  def ToDict(self):
1522 319856a9 Michael Hanselmann
    """Custom function for cluster.
1523 319856a9 Michael Hanselmann

1524 319856a9 Michael Hanselmann
    """
1525 b60ae2ca Iustin Pop
    mydict = super(Cluster, self).ToDict()
1526 319856a9 Michael Hanselmann
    mydict["tcpudp_port_pool"] = list(self.tcpudp_port_pool)
1527 319856a9 Michael Hanselmann
    return mydict
1528 319856a9 Michael Hanselmann
1529 319856a9 Michael Hanselmann
  @classmethod
1530 319856a9 Michael Hanselmann
  def FromDict(cls, val):
1531 319856a9 Michael Hanselmann
    """Custom function for cluster.
1532 319856a9 Michael Hanselmann

1533 319856a9 Michael Hanselmann
    """
1534 b60ae2ca Iustin Pop
    obj = super(Cluster, cls).FromDict(val)
1535 319856a9 Michael Hanselmann
    if not isinstance(obj.tcpudp_port_pool, set):
1536 319856a9 Michael Hanselmann
      obj.tcpudp_port_pool = set(obj.tcpudp_port_pool)
1537 319856a9 Michael Hanselmann
    return obj
1538 319856a9 Michael Hanselmann
1539 d63479b5 Iustin Pop
  def GetHVDefaults(self, hypervisor, os_name=None, skip_keys=None):
1540 d63479b5 Iustin Pop
    """Get the default hypervisor parameters for the cluster.
1541 d63479b5 Iustin Pop

1542 d63479b5 Iustin Pop
    @param hypervisor: the hypervisor name
1543 d63479b5 Iustin Pop
    @param os_name: if specified, we'll also update the defaults for this OS
1544 d63479b5 Iustin Pop
    @param skip_keys: if passed, list of keys not to use
1545 d63479b5 Iustin Pop
    @return: the defaults dict
1546 d63479b5 Iustin Pop

1547 d63479b5 Iustin Pop
    """
1548 d63479b5 Iustin Pop
    if skip_keys is None:
1549 d63479b5 Iustin Pop
      skip_keys = []
1550 d63479b5 Iustin Pop
1551 d63479b5 Iustin Pop
    fill_stack = [self.hvparams.get(hypervisor, {})]
1552 d63479b5 Iustin Pop
    if os_name is not None:
1553 d63479b5 Iustin Pop
      os_hvp = self.os_hvp.get(os_name, {}).get(hypervisor, {})
1554 d63479b5 Iustin Pop
      fill_stack.append(os_hvp)
1555 d63479b5 Iustin Pop
1556 d63479b5 Iustin Pop
    ret_dict = {}
1557 d63479b5 Iustin Pop
    for o_dict in fill_stack:
1558 d63479b5 Iustin Pop
      ret_dict = FillDict(ret_dict, o_dict, skip_keys=skip_keys)
1559 d63479b5 Iustin Pop
1560 d63479b5 Iustin Pop
    return ret_dict
1561 d63479b5 Iustin Pop
1562 73e0328b Iustin Pop
  def SimpleFillHV(self, hv_name, os_name, hvparams, skip_globals=False):
1563 73e0328b Iustin Pop
    """Fill a given hvparams dict with cluster defaults.
1564 73e0328b Iustin Pop

1565 73e0328b Iustin Pop
    @type hv_name: string
1566 73e0328b Iustin Pop
    @param hv_name: the hypervisor to use
1567 73e0328b Iustin Pop
    @type os_name: string
1568 73e0328b Iustin Pop
    @param os_name: the OS to use for overriding the hypervisor defaults
1569 73e0328b Iustin Pop
    @type skip_globals: boolean
1570 73e0328b Iustin Pop
    @param skip_globals: if True, the global hypervisor parameters will
1571 73e0328b Iustin Pop
        not be filled
1572 73e0328b Iustin Pop
    @rtype: dict
1573 73e0328b Iustin Pop
    @return: a copy of the given hvparams with missing keys filled from
1574 73e0328b Iustin Pop
        the cluster defaults
1575 73e0328b Iustin Pop

1576 73e0328b Iustin Pop
    """
1577 73e0328b Iustin Pop
    if skip_globals:
1578 73e0328b Iustin Pop
      skip_keys = constants.HVC_GLOBALS
1579 73e0328b Iustin Pop
    else:
1580 73e0328b Iustin Pop
      skip_keys = []
1581 73e0328b Iustin Pop
1582 73e0328b Iustin Pop
    def_dict = self.GetHVDefaults(hv_name, os_name, skip_keys=skip_keys)
1583 73e0328b Iustin Pop
    return FillDict(def_dict, hvparams, skip_keys=skip_keys)
1584 d63479b5 Iustin Pop
1585 7736a5f2 Iustin Pop
  def FillHV(self, instance, skip_globals=False):
1586 73e0328b Iustin Pop
    """Fill an instance's hvparams dict with cluster defaults.
1587 5bf7b5cf Iustin Pop

1588 a2a24f4c Guido Trotter
    @type instance: L{objects.Instance}
1589 5bf7b5cf Iustin Pop
    @param instance: the instance parameter to fill
1590 7736a5f2 Iustin Pop
    @type skip_globals: boolean
1591 7736a5f2 Iustin Pop
    @param skip_globals: if True, the global hypervisor parameters will
1592 7736a5f2 Iustin Pop
        not be filled
1593 5bf7b5cf Iustin Pop
    @rtype: dict
1594 5bf7b5cf Iustin Pop
    @return: a copy of the instance's hvparams with missing keys filled from
1595 5bf7b5cf Iustin Pop
        the cluster defaults
1596 5bf7b5cf Iustin Pop

1597 5bf7b5cf Iustin Pop
    """
1598 73e0328b Iustin Pop
    return self.SimpleFillHV(instance.hypervisor, instance.os,
1599 73e0328b Iustin Pop
                             instance.hvparams, skip_globals)
1600 17463d22 Renรฉ Nussbaumer
1601 73e0328b Iustin Pop
  def SimpleFillBE(self, beparams):
1602 73e0328b Iustin Pop
    """Fill a given beparams dict with cluster defaults.
1603 73e0328b Iustin Pop

1604 06596a60 Guido Trotter
    @type beparams: dict
1605 06596a60 Guido Trotter
    @param beparams: the dict to fill
1606 73e0328b Iustin Pop
    @rtype: dict
1607 73e0328b Iustin Pop
    @return: a copy of the passed in beparams with missing keys filled
1608 73e0328b Iustin Pop
        from the cluster defaults
1609 73e0328b Iustin Pop

1610 73e0328b Iustin Pop
    """
1611 73e0328b Iustin Pop
    return FillDict(self.beparams.get(constants.PP_DEFAULT, {}), beparams)
1612 5bf7b5cf Iustin Pop
1613 5bf7b5cf Iustin Pop
  def FillBE(self, instance):
1614 73e0328b Iustin Pop
    """Fill an instance's beparams dict with cluster defaults.
1615 5bf7b5cf Iustin Pop

1616 a2a24f4c Guido Trotter
    @type instance: L{objects.Instance}
1617 5bf7b5cf Iustin Pop
    @param instance: the instance parameter to fill
1618 5bf7b5cf Iustin Pop
    @rtype: dict
1619 5bf7b5cf Iustin Pop
    @return: a copy of the instance's beparams with missing keys filled from
1620 5bf7b5cf Iustin Pop
        the cluster defaults
1621 5bf7b5cf Iustin Pop

1622 5bf7b5cf Iustin Pop
    """
1623 73e0328b Iustin Pop
    return self.SimpleFillBE(instance.beparams)
1624 73e0328b Iustin Pop
1625 73e0328b Iustin Pop
  def SimpleFillNIC(self, nicparams):
1626 73e0328b Iustin Pop
    """Fill a given nicparams dict with cluster defaults.
1627 73e0328b Iustin Pop

1628 06596a60 Guido Trotter
    @type nicparams: dict
1629 06596a60 Guido Trotter
    @param nicparams: the dict to fill
1630 73e0328b Iustin Pop
    @rtype: dict
1631 73e0328b Iustin Pop
    @return: a copy of the passed in nicparams with missing keys filled
1632 73e0328b Iustin Pop
        from the cluster defaults
1633 73e0328b Iustin Pop

1634 73e0328b Iustin Pop
    """
1635 73e0328b Iustin Pop
    return FillDict(self.nicparams.get(constants.PP_DEFAULT, {}), nicparams)
1636 5bf7b5cf Iustin Pop
1637 1bdcbbab Iustin Pop
  def SimpleFillOS(self, os_name, os_params):
1638 1bdcbbab Iustin Pop
    """Fill an instance's osparams dict with cluster defaults.
1639 1bdcbbab Iustin Pop

1640 1bdcbbab Iustin Pop
    @type os_name: string
1641 1bdcbbab Iustin Pop
    @param os_name: the OS name to use
1642 1bdcbbab Iustin Pop
    @type os_params: dict
1643 1bdcbbab Iustin Pop
    @param os_params: the dict to fill with default values
1644 1bdcbbab Iustin Pop
    @rtype: dict
1645 1bdcbbab Iustin Pop
    @return: a copy of the instance's osparams with missing keys filled from
1646 1bdcbbab Iustin Pop
        the cluster defaults
1647 1bdcbbab Iustin Pop

1648 1bdcbbab Iustin Pop
    """
1649 1bdcbbab Iustin Pop
    name_only = os_name.split("+", 1)[0]
1650 1bdcbbab Iustin Pop
    # base OS
1651 1bdcbbab Iustin Pop
    result = self.osparams.get(name_only, {})
1652 1bdcbbab Iustin Pop
    # OS with variant
1653 1bdcbbab Iustin Pop
    result = FillDict(result, self.osparams.get(os_name, {}))
1654 1bdcbbab Iustin Pop
    # specified params
1655 1bdcbbab Iustin Pop
    return FillDict(result, os_params)
1656 1bdcbbab Iustin Pop
1657 2da9f556 Renรฉ Nussbaumer
  @staticmethod
1658 2da9f556 Renรฉ Nussbaumer
  def SimpleFillHvState(hv_state):
1659 2da9f556 Renรฉ Nussbaumer
    """Fill an hv_state sub dict with cluster defaults.
1660 2da9f556 Renรฉ Nussbaumer

1661 2da9f556 Renรฉ Nussbaumer
    """
1662 2da9f556 Renรฉ Nussbaumer
    return FillDict(constants.HVST_DEFAULTS, hv_state)
1663 2da9f556 Renรฉ Nussbaumer
1664 2da9f556 Renรฉ Nussbaumer
  @staticmethod
1665 2da9f556 Renรฉ Nussbaumer
  def SimpleFillDiskState(disk_state):
1666 2da9f556 Renรฉ Nussbaumer
    """Fill an disk_state sub dict with cluster defaults.
1667 2da9f556 Renรฉ Nussbaumer

1668 2da9f556 Renรฉ Nussbaumer
    """
1669 2da9f556 Renรฉ Nussbaumer
    return FillDict(constants.DS_DEFAULTS, disk_state)
1670 2da9f556 Renรฉ Nussbaumer
1671 095e71aa Renรฉ Nussbaumer
  def FillND(self, node, nodegroup):
1672 ce523de1 Michael Hanselmann
    """Return filled out ndparams for L{objects.NodeGroup} and L{objects.Node}
1673 095e71aa Renรฉ Nussbaumer

1674 095e71aa Renรฉ Nussbaumer
    @type node: L{objects.Node}
1675 095e71aa Renรฉ Nussbaumer
    @param node: A Node object to fill
1676 095e71aa Renรฉ Nussbaumer
    @type nodegroup: L{objects.NodeGroup}
1677 095e71aa Renรฉ Nussbaumer
    @param nodegroup: A Node object to fill
1678 095e71aa Renรฉ Nussbaumer
    @return a copy of the node's ndparams with defaults filled
1679 095e71aa Renรฉ Nussbaumer

1680 095e71aa Renรฉ Nussbaumer
    """
1681 095e71aa Renรฉ Nussbaumer
    return self.SimpleFillND(nodegroup.FillND(node))
1682 095e71aa Renรฉ Nussbaumer
1683 095e71aa Renรฉ Nussbaumer
  def SimpleFillND(self, ndparams):
1684 095e71aa Renรฉ Nussbaumer
    """Fill a given ndparams dict with defaults.
1685 095e71aa Renรฉ Nussbaumer

1686 095e71aa Renรฉ Nussbaumer
    @type ndparams: dict
1687 095e71aa Renรฉ Nussbaumer
    @param ndparams: the dict to fill
1688 095e71aa Renรฉ Nussbaumer
    @rtype: dict
1689 095e71aa Renรฉ Nussbaumer
    @return: a copy of the passed in ndparams with missing keys filled
1690 095e71aa Renรฉ Nussbaumer
        from the cluster defaults
1691 095e71aa Renรฉ Nussbaumer

1692 095e71aa Renรฉ Nussbaumer
    """
1693 095e71aa Renรฉ Nussbaumer
    return FillDict(self.ndparams, ndparams)
1694 095e71aa Renรฉ Nussbaumer
1695 918eb80b Agata Murawska
  def SimpleFillIPolicy(self, ipolicy):
1696 918eb80b Agata Murawska
    """ Fill instance policy dict with defaults.
1697 918eb80b Agata Murawska

1698 918eb80b Agata Murawska
    @type ipolicy: dict
1699 918eb80b Agata Murawska
    @param ipolicy: the dict to fill
1700 918eb80b Agata Murawska
    @rtype: dict
1701 918eb80b Agata Murawska
    @return: a copy of passed ipolicy with missing keys filled from
1702 918eb80b Agata Murawska
      the cluster defaults
1703 918eb80b Agata Murawska

1704 918eb80b Agata Murawska
    """
1705 2cc673a3 Iustin Pop
    return FillIPolicy(self.ipolicy, ipolicy)
1706 918eb80b Agata Murawska
1707 5c947f38 Iustin Pop
1708 96acbc09 Michael Hanselmann
class BlockDevStatus(ConfigObject):
1709 96acbc09 Michael Hanselmann
  """Config object representing the status of a block device."""
1710 96acbc09 Michael Hanselmann
  __slots__ = [
1711 96acbc09 Michael Hanselmann
    "dev_path",
1712 96acbc09 Michael Hanselmann
    "major",
1713 96acbc09 Michael Hanselmann
    "minor",
1714 96acbc09 Michael Hanselmann
    "sync_percent",
1715 96acbc09 Michael Hanselmann
    "estimated_time",
1716 96acbc09 Michael Hanselmann
    "is_degraded",
1717 f208978a Michael Hanselmann
    "ldisk_status",
1718 96acbc09 Michael Hanselmann
    ]
1719 96acbc09 Michael Hanselmann
1720 96acbc09 Michael Hanselmann
1721 2d76b580 Michael Hanselmann
class ImportExportStatus(ConfigObject):
1722 2d76b580 Michael Hanselmann
  """Config object representing the status of an import or export."""
1723 2d76b580 Michael Hanselmann
  __slots__ = [
1724 2d76b580 Michael Hanselmann
    "recent_output",
1725 2d76b580 Michael Hanselmann
    "listen_port",
1726 2d76b580 Michael Hanselmann
    "connected",
1727 c08d76f5 Michael Hanselmann
    "progress_mbytes",
1728 c08d76f5 Michael Hanselmann
    "progress_throughput",
1729 c08d76f5 Michael Hanselmann
    "progress_eta",
1730 c08d76f5 Michael Hanselmann
    "progress_percent",
1731 2d76b580 Michael Hanselmann
    "exit_status",
1732 2d76b580 Michael Hanselmann
    "error_message",
1733 2d76b580 Michael Hanselmann
    ] + _TIMESTAMPS
1734 2d76b580 Michael Hanselmann
1735 2d76b580 Michael Hanselmann
1736 eb630f50 Michael Hanselmann
class ImportExportOptions(ConfigObject):
1737 eb630f50 Michael Hanselmann
  """Options for import/export daemon
1738 eb630f50 Michael Hanselmann

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

1746 eb630f50 Michael Hanselmann
  """
1747 eb630f50 Michael Hanselmann
  __slots__ = [
1748 eb630f50 Michael Hanselmann
    "key_name",
1749 eb630f50 Michael Hanselmann
    "ca_pem",
1750 a5310c2a Michael Hanselmann
    "compress",
1751 af1d39b1 Michael Hanselmann
    "magic",
1752 855d2fc7 Michael Hanselmann
    "ipv6",
1753 4478301b Michael Hanselmann
    "connect_timeout",
1754 eb630f50 Michael Hanselmann
    ]
1755 eb630f50 Michael Hanselmann
1756 eb630f50 Michael Hanselmann
1757 18d750b9 Guido Trotter
class ConfdRequest(ConfigObject):
1758 18d750b9 Guido Trotter
  """Object holding a confd request.
1759 18d750b9 Guido Trotter

1760 18d750b9 Guido Trotter
  @ivar protocol: confd protocol version
1761 18d750b9 Guido Trotter
  @ivar type: confd query type
1762 18d750b9 Guido Trotter
  @ivar query: query request
1763 18d750b9 Guido Trotter
  @ivar rsalt: requested reply salt
1764 18d750b9 Guido Trotter

1765 18d750b9 Guido Trotter
  """
1766 18d750b9 Guido Trotter
  __slots__ = [
1767 18d750b9 Guido Trotter
    "protocol",
1768 18d750b9 Guido Trotter
    "type",
1769 18d750b9 Guido Trotter
    "query",
1770 18d750b9 Guido Trotter
    "rsalt",
1771 18d750b9 Guido Trotter
    ]
1772 18d750b9 Guido Trotter
1773 18d750b9 Guido Trotter
1774 18d750b9 Guido Trotter
class ConfdReply(ConfigObject):
1775 18d750b9 Guido Trotter
  """Object holding a confd reply.
1776 18d750b9 Guido Trotter

1777 18d750b9 Guido Trotter
  @ivar protocol: confd protocol version
1778 18d750b9 Guido Trotter
  @ivar status: reply status code (ok, error)
1779 18d750b9 Guido Trotter
  @ivar answer: confd query reply
1780 18d750b9 Guido Trotter
  @ivar serial: configuration serial number
1781 18d750b9 Guido Trotter

1782 18d750b9 Guido Trotter
  """
1783 18d750b9 Guido Trotter
  __slots__ = [
1784 18d750b9 Guido Trotter
    "protocol",
1785 18d750b9 Guido Trotter
    "status",
1786 18d750b9 Guido Trotter
    "answer",
1787 18d750b9 Guido Trotter
    "serial",
1788 18d750b9 Guido Trotter
    ]
1789 18d750b9 Guido Trotter
1790 18d750b9 Guido Trotter
1791 707f23b5 Michael Hanselmann
class QueryFieldDefinition(ConfigObject):
1792 707f23b5 Michael Hanselmann
  """Object holding a query field definition.
1793 707f23b5 Michael Hanselmann

1794 24d6d3e2 Michael Hanselmann
  @ivar name: Field name
1795 707f23b5 Michael Hanselmann
  @ivar title: Human-readable title
1796 707f23b5 Michael Hanselmann
  @ivar kind: Field type
1797 1ae17369 Michael Hanselmann
  @ivar doc: Human-readable description
1798 707f23b5 Michael Hanselmann

1799 707f23b5 Michael Hanselmann
  """
1800 707f23b5 Michael Hanselmann
  __slots__ = [
1801 707f23b5 Michael Hanselmann
    "name",
1802 707f23b5 Michael Hanselmann
    "title",
1803 707f23b5 Michael Hanselmann
    "kind",
1804 1ae17369 Michael Hanselmann
    "doc",
1805 707f23b5 Michael Hanselmann
    ]
1806 707f23b5 Michael Hanselmann
1807 707f23b5 Michael Hanselmann
1808 0538c375 Michael Hanselmann
class _QueryResponseBase(ConfigObject):
1809 0538c375 Michael Hanselmann
  __slots__ = [
1810 0538c375 Michael Hanselmann
    "fields",
1811 0538c375 Michael Hanselmann
    ]
1812 0538c375 Michael Hanselmann
1813 0538c375 Michael Hanselmann
  def ToDict(self):
1814 0538c375 Michael Hanselmann
    """Custom function for serializing.
1815 0538c375 Michael Hanselmann

1816 0538c375 Michael Hanselmann
    """
1817 0538c375 Michael Hanselmann
    mydict = super(_QueryResponseBase, self).ToDict()
1818 0538c375 Michael Hanselmann
    mydict["fields"] = self._ContainerToDicts(mydict["fields"])
1819 0538c375 Michael Hanselmann
    return mydict
1820 0538c375 Michael Hanselmann
1821 0538c375 Michael Hanselmann
  @classmethod
1822 0538c375 Michael Hanselmann
  def FromDict(cls, val):
1823 0538c375 Michael Hanselmann
    """Custom function for de-serializing.
1824 0538c375 Michael Hanselmann

1825 0538c375 Michael Hanselmann
    """
1826 0538c375 Michael Hanselmann
    obj = super(_QueryResponseBase, cls).FromDict(val)
1827 0538c375 Michael Hanselmann
    obj.fields = cls._ContainerFromDicts(obj.fields, list, QueryFieldDefinition)
1828 0538c375 Michael Hanselmann
    return obj
1829 0538c375 Michael Hanselmann
1830 0538c375 Michael Hanselmann
1831 24d6d3e2 Michael Hanselmann
class QueryRequest(ConfigObject):
1832 24d6d3e2 Michael Hanselmann
  """Object holding a query request.
1833 24d6d3e2 Michael Hanselmann

1834 24d6d3e2 Michael Hanselmann
  """
1835 24d6d3e2 Michael Hanselmann
  __slots__ = [
1836 24d6d3e2 Michael Hanselmann
    "what",
1837 24d6d3e2 Michael Hanselmann
    "fields",
1838 2e5c33db Iustin Pop
    "qfilter",
1839 24d6d3e2 Michael Hanselmann
    ]
1840 24d6d3e2 Michael Hanselmann
1841 24d6d3e2 Michael Hanselmann
1842 0538c375 Michael Hanselmann
class QueryResponse(_QueryResponseBase):
1843 24d6d3e2 Michael Hanselmann
  """Object holding the response to a query.
1844 24d6d3e2 Michael Hanselmann

1845 24d6d3e2 Michael Hanselmann
  @ivar fields: List of L{QueryFieldDefinition} objects
1846 24d6d3e2 Michael Hanselmann
  @ivar data: Requested data
1847 24d6d3e2 Michael Hanselmann

1848 24d6d3e2 Michael Hanselmann
  """
1849 24d6d3e2 Michael Hanselmann
  __slots__ = [
1850 24d6d3e2 Michael Hanselmann
    "data",
1851 24d6d3e2 Michael Hanselmann
    ]
1852 24d6d3e2 Michael Hanselmann
1853 24d6d3e2 Michael Hanselmann
1854 24d6d3e2 Michael Hanselmann
class QueryFieldsRequest(ConfigObject):
1855 24d6d3e2 Michael Hanselmann
  """Object holding a request for querying available fields.
1856 24d6d3e2 Michael Hanselmann

1857 24d6d3e2 Michael Hanselmann
  """
1858 24d6d3e2 Michael Hanselmann
  __slots__ = [
1859 24d6d3e2 Michael Hanselmann
    "what",
1860 24d6d3e2 Michael Hanselmann
    "fields",
1861 24d6d3e2 Michael Hanselmann
    ]
1862 24d6d3e2 Michael Hanselmann
1863 24d6d3e2 Michael Hanselmann
1864 0538c375 Michael Hanselmann
class QueryFieldsResponse(_QueryResponseBase):
1865 24d6d3e2 Michael Hanselmann
  """Object holding the response to a query for fields.
1866 24d6d3e2 Michael Hanselmann

1867 24d6d3e2 Michael Hanselmann
  @ivar fields: List of L{QueryFieldDefinition} objects
1868 24d6d3e2 Michael Hanselmann

1869 24d6d3e2 Michael Hanselmann
  """
1870 24d6d3e2 Michael Hanselmann
  __slots__ = [
1871 24d6d3e2 Michael Hanselmann
    ]
1872 24d6d3e2 Michael Hanselmann
1873 24d6d3e2 Michael Hanselmann
1874 6a1434d7 Andrea Spadaccini
class MigrationStatus(ConfigObject):
1875 6a1434d7 Andrea Spadaccini
  """Object holding the status of a migration.
1876 6a1434d7 Andrea Spadaccini

1877 6a1434d7 Andrea Spadaccini
  """
1878 6a1434d7 Andrea Spadaccini
  __slots__ = [
1879 6a1434d7 Andrea Spadaccini
    "status",
1880 6a1434d7 Andrea Spadaccini
    "transferred_ram",
1881 6a1434d7 Andrea Spadaccini
    "total_ram",
1882 6a1434d7 Andrea Spadaccini
    ]
1883 6a1434d7 Andrea Spadaccini
1884 6a1434d7 Andrea Spadaccini
1885 25ce3ec4 Michael Hanselmann
class InstanceConsole(ConfigObject):
1886 25ce3ec4 Michael Hanselmann
  """Object describing how to access the console of an instance.
1887 25ce3ec4 Michael Hanselmann

1888 25ce3ec4 Michael Hanselmann
  """
1889 25ce3ec4 Michael Hanselmann
  __slots__ = [
1890 25ce3ec4 Michael Hanselmann
    "instance",
1891 25ce3ec4 Michael Hanselmann
    "kind",
1892 25ce3ec4 Michael Hanselmann
    "message",
1893 25ce3ec4 Michael Hanselmann
    "host",
1894 25ce3ec4 Michael Hanselmann
    "port",
1895 25ce3ec4 Michael Hanselmann
    "user",
1896 25ce3ec4 Michael Hanselmann
    "command",
1897 25ce3ec4 Michael Hanselmann
    "display",
1898 25ce3ec4 Michael Hanselmann
    ]
1899 25ce3ec4 Michael Hanselmann
1900 25ce3ec4 Michael Hanselmann
  def Validate(self):
1901 25ce3ec4 Michael Hanselmann
    """Validates contents of this object.
1902 25ce3ec4 Michael Hanselmann

1903 25ce3ec4 Michael Hanselmann
    """
1904 25ce3ec4 Michael Hanselmann
    assert self.kind in constants.CONS_ALL, "Unknown console type"
1905 25ce3ec4 Michael Hanselmann
    assert self.instance, "Missing instance name"
1906 4d2cdb5a Andrea Spadaccini
    assert self.message or self.kind in [constants.CONS_SSH,
1907 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1908 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_VNC]
1909 25ce3ec4 Michael Hanselmann
    assert self.host or self.kind == constants.CONS_MESSAGE
1910 25ce3ec4 Michael Hanselmann
    assert self.port or self.kind in [constants.CONS_MESSAGE,
1911 25ce3ec4 Michael Hanselmann
                                      constants.CONS_SSH]
1912 25ce3ec4 Michael Hanselmann
    assert self.user or self.kind in [constants.CONS_MESSAGE,
1913 4d2cdb5a Andrea Spadaccini
                                      constants.CONS_SPICE,
1914 25ce3ec4 Michael Hanselmann
                                      constants.CONS_VNC]
1915 25ce3ec4 Michael Hanselmann
    assert self.command or self.kind in [constants.CONS_MESSAGE,
1916 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1917 25ce3ec4 Michael Hanselmann
                                         constants.CONS_VNC]
1918 25ce3ec4 Michael Hanselmann
    assert self.display or self.kind in [constants.CONS_MESSAGE,
1919 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1920 25ce3ec4 Michael Hanselmann
                                         constants.CONS_SSH]
1921 25ce3ec4 Michael Hanselmann
    return True
1922 25ce3ec4 Michael Hanselmann
1923 25ce3ec4 Michael Hanselmann
1924 a8083063 Iustin Pop
class SerializableConfigParser(ConfigParser.SafeConfigParser):
1925 a8083063 Iustin Pop
  """Simple wrapper over ConfigParse that allows serialization.
1926 a8083063 Iustin Pop

1927 a8083063 Iustin Pop
  This class is basically ConfigParser.SafeConfigParser with two
1928 a8083063 Iustin Pop
  additional methods that allow it to serialize/unserialize to/from a
1929 a8083063 Iustin Pop
  buffer.
1930 a8083063 Iustin Pop

1931 a8083063 Iustin Pop
  """
1932 a8083063 Iustin Pop
  def Dumps(self):
1933 a8083063 Iustin Pop
    """Dump this instance and return the string representation."""
1934 a8083063 Iustin Pop
    buf = StringIO()
1935 a8083063 Iustin Pop
    self.write(buf)
1936 a8083063 Iustin Pop
    return buf.getvalue()
1937 a8083063 Iustin Pop
1938 b39bf4bb Guido Trotter
  @classmethod
1939 b39bf4bb Guido Trotter
  def Loads(cls, data):
1940 a8083063 Iustin Pop
    """Load data from a string."""
1941 a8083063 Iustin Pop
    buf = StringIO(data)
1942 b39bf4bb Guido Trotter
    cfp = cls()
1943 a8083063 Iustin Pop
    cfp.readfp(buf)
1944 a8083063 Iustin Pop
    return cfp