Statistics
| Branch: | Tag: | Revision:

root / lib / objects.py @ 68a856ef

History | View | Annotate | Download (53.3 kB)

1 2f31098c Iustin Pop
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 6d33a6eb Iustin Pop
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 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 32017174 Agata Murawska
}
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 918eb80b Agata Murawska
def FillDictOfDicts(defaults_dict, custom_dict, skip_keys=None):
96 918eb80b Agata Murawska
  """Run FillDict for each key in dictionary.
97 918eb80b Agata Murawska

98 918eb80b Agata Murawska
  """
99 918eb80b Agata Murawska
  ret_dict = {}
100 918eb80b Agata Murawska
  for key in defaults_dict.keys():
101 918eb80b Agata Murawska
    ret_dict[key] = FillDict(defaults_dict[key],
102 918eb80b Agata Murawska
                             custom_dict.get(key, {}),
103 918eb80b Agata Murawska
                             skip_keys=skip_keys)
104 918eb80b Agata Murawska
  return ret_dict
105 918eb80b Agata Murawska
106 918eb80b Agata Murawska
107 6e34b628 Guido Trotter
def UpgradeGroupedParams(target, defaults):
108 6e34b628 Guido Trotter
  """Update all groups for the target parameter.
109 6e34b628 Guido Trotter

110 6e34b628 Guido Trotter
  @type target: dict of dicts
111 6e34b628 Guido Trotter
  @param target: {group: {parameter: value}}
112 6e34b628 Guido Trotter
  @type defaults: dict
113 6e34b628 Guido Trotter
  @param defaults: default parameter values
114 6e34b628 Guido Trotter

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

127 8c72ab2b Guido Trotter
  @type target: dict
128 8c72ab2b Guido Trotter
  @param target: "be" parameters dict
129 8c72ab2b Guido Trotter

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

141 bc5d0215 Andrea Spadaccini
  @type diskparams: dict
142 bc5d0215 Andrea Spadaccini
  @param diskparams: disk parameters to upgrade
143 bc5d0215 Andrea Spadaccini
  @rtype: dict
144 bc5d0215 Andrea Spadaccini
  @return: the upgraded disk parameters dit
145 bc5d0215 Andrea Spadaccini

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

167 918eb80b Agata Murawska
  """
168 918eb80b Agata Murawska
  return dict([
169 4f725341 Agata Murawska
    (constants.ISPECS_MIN, dict()),
170 4f725341 Agata Murawska
    (constants.ISPECS_MAX, dict()),
171 4f725341 Agata Murawska
    (constants.ISPECS_STD, dict()),
172 918eb80b Agata Murawska
    ])
173 918eb80b Agata Murawska
174 918eb80b Agata Murawska
175 32017174 Agata Murawska
def CreateIPolicyFromOpts(ispecs_mem_size=None,
176 32017174 Agata Murawska
                          ispecs_cpu_count=None,
177 32017174 Agata Murawska
                          ispecs_disk_count=None,
178 32017174 Agata Murawska
                          ispecs_disk_size=None,
179 32017174 Agata Murawska
                          ispecs_nic_count=None,
180 32017174 Agata Murawska
                          group_ipolicy=False,
181 32017174 Agata Murawska
                          allowed_values=None):
182 32017174 Agata Murawska
  """Creation of instane policy based on command line options.
183 32017174 Agata Murawska

184 32017174 Agata Murawska

185 32017174 Agata Murawska
  """
186 32017174 Agata Murawska
  # prepare ipolicy dict
187 32017174 Agata Murawska
  ipolicy_transposed = {
188 4f725341 Agata Murawska
    constants.ISPEC_MEM_SIZE: ispecs_mem_size,
189 4f725341 Agata Murawska
    constants.ISPEC_CPU_COUNT: ispecs_cpu_count,
190 4f725341 Agata Murawska
    constants.ISPEC_DISK_COUNT: ispecs_disk_count,
191 4f725341 Agata Murawska
    constants.ISPEC_DISK_SIZE: ispecs_disk_size,
192 4f725341 Agata Murawska
    constants.ISPEC_NIC_COUNT: ispecs_nic_count,
193 32017174 Agata Murawska
    }
194 32017174 Agata Murawska
195 32017174 Agata Murawska
  # first, check that the values given are correct
196 32017174 Agata Murawska
  if group_ipolicy:
197 32017174 Agata Murawska
    forced_type = TISPECS_GROUP_TYPES
198 32017174 Agata Murawska
  else:
199 32017174 Agata Murawska
    forced_type = TISPECS_CLUSTER_TYPES
200 32017174 Agata Murawska
201 32017174 Agata Murawska
  for specs in ipolicy_transposed.values():
202 32017174 Agata Murawska
    utils.ForceDictType(specs, forced_type, allowed_values=allowed_values)
203 32017174 Agata Murawska
204 32017174 Agata Murawska
  # then transpose
205 32017174 Agata Murawska
  ipolicy_out = MakeEmptyIPolicy()
206 32017174 Agata Murawska
  for name, specs in ipolicy_transposed.iteritems():
207 32017174 Agata Murawska
    assert name in constants.ISPECS_PARAMETERS
208 32017174 Agata Murawska
    for key, val in specs.items(): # {min: .. ,max: .., std: ..}
209 32017174 Agata Murawska
      ipolicy_out[key][name] = val
210 32017174 Agata Murawska
211 32017174 Agata Murawska
  return ipolicy_out
212 32017174 Agata Murawska
213 32017174 Agata Murawska
214 a8083063 Iustin Pop
class ConfigObject(object):
215 a8083063 Iustin Pop
  """A generic config object.
216 a8083063 Iustin Pop

217 a8083063 Iustin Pop
  It has the following properties:
218 a8083063 Iustin Pop

219 a8083063 Iustin Pop
    - provides somewhat safe recursive unpickling and pickling for its classes
220 a8083063 Iustin Pop
    - unset attributes which are defined in slots are always returned
221 a8083063 Iustin Pop
      as None instead of raising an error
222 a8083063 Iustin Pop

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

226 a8083063 Iustin Pop
  """
227 a8083063 Iustin Pop
  __slots__ = []
228 a8083063 Iustin Pop
229 a8083063 Iustin Pop
  def __init__(self, **kwargs):
230 319856a9 Michael Hanselmann
    for k, v in kwargs.iteritems():
231 319856a9 Michael Hanselmann
      setattr(self, k, v)
232 a8083063 Iustin Pop
233 a8083063 Iustin Pop
  def __getattr__(self, name):
234 adf385c7 Iustin Pop
    if name not in self._all_slots():
235 3ecf6786 Iustin Pop
      raise AttributeError("Invalid object attribute %s.%s" %
236 3ecf6786 Iustin Pop
                           (type(self).__name__, name))
237 a8083063 Iustin Pop
    return None
238 a8083063 Iustin Pop
239 a8083063 Iustin Pop
  def __setstate__(self, state):
240 adf385c7 Iustin Pop
    slots = self._all_slots()
241 a8083063 Iustin Pop
    for name in state:
242 adf385c7 Iustin Pop
      if name in slots:
243 a8083063 Iustin Pop
        setattr(self, name, state[name])
244 a8083063 Iustin Pop
245 adf385c7 Iustin Pop
  @classmethod
246 adf385c7 Iustin Pop
  def _all_slots(cls):
247 adf385c7 Iustin Pop
    """Compute the list of all declared slots for a class.
248 adf385c7 Iustin Pop

249 adf385c7 Iustin Pop
    """
250 adf385c7 Iustin Pop
    slots = []
251 adf385c7 Iustin Pop
    for parent in cls.__mro__:
252 adf385c7 Iustin Pop
      slots.extend(getattr(parent, "__slots__", []))
253 adf385c7 Iustin Pop
    return slots
254 adf385c7 Iustin Pop
255 ff9c047c Iustin Pop
  def ToDict(self):
256 ff9c047c Iustin Pop
    """Convert to a dict holding only standard python types.
257 ff9c047c Iustin Pop

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

264 ff9c047c Iustin Pop
    """
265 4c14965f Guido Trotter
    result = {}
266 adf385c7 Iustin Pop
    for name in self._all_slots():
267 4c14965f Guido Trotter
      value = getattr(self, name, None)
268 4c14965f Guido Trotter
      if value is not None:
269 4c14965f Guido Trotter
        result[name] = value
270 4c14965f Guido Trotter
    return result
271 4c14965f Guido Trotter
272 4c14965f Guido Trotter
  __getstate__ = ToDict
273 ff9c047c Iustin Pop
274 ff9c047c Iustin Pop
  @classmethod
275 ff9c047c Iustin Pop
  def FromDict(cls, val):
276 ff9c047c Iustin Pop
    """Create an object from a dictionary.
277 ff9c047c Iustin Pop

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

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

286 ff9c047c Iustin Pop
    """
287 ff9c047c Iustin Pop
    if not isinstance(val, dict):
288 ff9c047c Iustin Pop
      raise errors.ConfigurationError("Invalid object passed to FromDict:"
289 ff9c047c Iustin Pop
                                      " expected dict, got %s" % type(val))
290 319856a9 Michael Hanselmann
    val_str = dict([(str(k), v) for k, v in val.iteritems()])
291 b459a848 Andrea Spadaccini
    obj = cls(**val_str) # pylint: disable=W0142
292 ff9c047c Iustin Pop
    return obj
293 ff9c047c Iustin Pop
294 ff9c047c Iustin Pop
  @staticmethod
295 ff9c047c Iustin Pop
  def _ContainerToDicts(container):
296 ff9c047c Iustin Pop
    """Convert the elements of a container to standard python types.
297 ff9c047c Iustin Pop

298 ff9c047c Iustin Pop
    This method converts a container with elements derived from
299 ff9c047c Iustin Pop
    ConfigData to standard python types. If the container is a dict,
300 ff9c047c Iustin Pop
    we don't touch the keys, only the values.
301 ff9c047c Iustin Pop

302 ff9c047c Iustin Pop
    """
303 ff9c047c Iustin Pop
    if isinstance(container, dict):
304 ff9c047c Iustin Pop
      ret = dict([(k, v.ToDict()) for k, v in container.iteritems()])
305 ff9c047c Iustin Pop
    elif isinstance(container, (list, tuple, set, frozenset)):
306 ff9c047c Iustin Pop
      ret = [elem.ToDict() for elem in container]
307 ff9c047c Iustin Pop
    else:
308 ff9c047c Iustin Pop
      raise TypeError("Invalid type %s passed to _ContainerToDicts" %
309 ff9c047c Iustin Pop
                      type(container))
310 ff9c047c Iustin Pop
    return ret
311 ff9c047c Iustin Pop
312 ff9c047c Iustin Pop
  @staticmethod
313 ff9c047c Iustin Pop
  def _ContainerFromDicts(source, c_type, e_type):
314 ff9c047c Iustin Pop
    """Convert a container from standard python types.
315 ff9c047c Iustin Pop

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

320 ff9c047c Iustin Pop
    """
321 ff9c047c Iustin Pop
    if not isinstance(c_type, type):
322 ff9c047c Iustin Pop
      raise TypeError("Container type %s passed to _ContainerFromDicts is"
323 ff9c047c Iustin Pop
                      " not a type" % type(c_type))
324 fe25a79a Guido Trotter
    if source is None:
325 fe25a79a Guido Trotter
      source = c_type()
326 ff9c047c Iustin Pop
    if c_type is dict:
327 ff9c047c Iustin Pop
      ret = dict([(k, e_type.FromDict(v)) for k, v in source.iteritems()])
328 ff9c047c Iustin Pop
    elif c_type in (list, tuple, set, frozenset):
329 ff9c047c Iustin Pop
      ret = c_type([e_type.FromDict(elem) for elem in source])
330 ff9c047c Iustin Pop
    else:
331 ff9c047c Iustin Pop
      raise TypeError("Invalid container type %s passed to"
332 ff9c047c Iustin Pop
                      " _ContainerFromDicts" % c_type)
333 ff9c047c Iustin Pop
    return ret
334 ff9c047c Iustin Pop
335 e8d563f3 Iustin Pop
  def Copy(self):
336 e8d563f3 Iustin Pop
    """Makes a deep copy of the current object and its children.
337 e8d563f3 Iustin Pop

338 e8d563f3 Iustin Pop
    """
339 e8d563f3 Iustin Pop
    dict_form = self.ToDict()
340 e8d563f3 Iustin Pop
    clone_obj = self.__class__.FromDict(dict_form)
341 e8d563f3 Iustin Pop
    return clone_obj
342 e8d563f3 Iustin Pop
343 ff9c047c Iustin Pop
  def __repr__(self):
344 ff9c047c Iustin Pop
    """Implement __repr__ for ConfigObjects."""
345 ff9c047c Iustin Pop
    return repr(self.ToDict())
346 ff9c047c Iustin Pop
347 560428be Guido Trotter
  def UpgradeConfig(self):
348 560428be Guido Trotter
    """Fill defaults for missing configuration values.
349 560428be Guido Trotter

350 90d726a8 Iustin Pop
    This method will be called at configuration load time, and its
351 90d726a8 Iustin Pop
    implementation will be object dependent.
352 560428be Guido Trotter

353 560428be Guido Trotter
    """
354 560428be Guido Trotter
    pass
355 560428be Guido Trotter
356 a8083063 Iustin Pop
357 ec29fe40 Iustin Pop
class TaggableObject(ConfigObject):
358 5c947f38 Iustin Pop
  """An generic class supporting tags.
359 5c947f38 Iustin Pop

360 5c947f38 Iustin Pop
  """
361 154b9580 Balazs Lecz
  __slots__ = ["tags"]
362 b5e5632e Iustin Pop
  VALID_TAG_RE = re.compile("^[\w.+*/:@-]+$")
363 2057f6c7 Iustin Pop
364 b5e5632e Iustin Pop
  @classmethod
365 b5e5632e Iustin Pop
  def ValidateTag(cls, tag):
366 5c947f38 Iustin Pop
    """Check if a tag is valid.
367 5c947f38 Iustin Pop

368 5c947f38 Iustin Pop
    If the tag is invalid, an errors.TagError will be raised. The
369 5c947f38 Iustin Pop
    function has no return value.
370 5c947f38 Iustin Pop

371 5c947f38 Iustin Pop
    """
372 5c947f38 Iustin Pop
    if not isinstance(tag, basestring):
373 3ecf6786 Iustin Pop
      raise errors.TagError("Invalid tag type (not a string)")
374 5c947f38 Iustin Pop
    if len(tag) > constants.MAX_TAG_LEN:
375 319856a9 Michael Hanselmann
      raise errors.TagError("Tag too long (>%d characters)" %
376 319856a9 Michael Hanselmann
                            constants.MAX_TAG_LEN)
377 5c947f38 Iustin Pop
    if not tag:
378 3ecf6786 Iustin Pop
      raise errors.TagError("Tags cannot be empty")
379 b5e5632e Iustin Pop
    if not cls.VALID_TAG_RE.match(tag):
380 3ecf6786 Iustin Pop
      raise errors.TagError("Tag contains invalid characters")
381 5c947f38 Iustin Pop
382 5c947f38 Iustin Pop
  def GetTags(self):
383 5c947f38 Iustin Pop
    """Return the tags list.
384 5c947f38 Iustin Pop

385 5c947f38 Iustin Pop
    """
386 5c947f38 Iustin Pop
    tags = getattr(self, "tags", None)
387 5c947f38 Iustin Pop
    if tags is None:
388 5c947f38 Iustin Pop
      tags = self.tags = set()
389 5c947f38 Iustin Pop
    return tags
390 5c947f38 Iustin Pop
391 5c947f38 Iustin Pop
  def AddTag(self, tag):
392 5c947f38 Iustin Pop
    """Add a new tag.
393 5c947f38 Iustin Pop

394 5c947f38 Iustin Pop
    """
395 5c947f38 Iustin Pop
    self.ValidateTag(tag)
396 5c947f38 Iustin Pop
    tags = self.GetTags()
397 5c947f38 Iustin Pop
    if len(tags) >= constants.MAX_TAGS_PER_OBJ:
398 3ecf6786 Iustin Pop
      raise errors.TagError("Too many tags")
399 5c947f38 Iustin Pop
    self.GetTags().add(tag)
400 5c947f38 Iustin Pop
401 5c947f38 Iustin Pop
  def RemoveTag(self, tag):
402 5c947f38 Iustin Pop
    """Remove a tag.
403 5c947f38 Iustin Pop

404 5c947f38 Iustin Pop
    """
405 5c947f38 Iustin Pop
    self.ValidateTag(tag)
406 5c947f38 Iustin Pop
    tags = self.GetTags()
407 5c947f38 Iustin Pop
    try:
408 5c947f38 Iustin Pop
      tags.remove(tag)
409 5c947f38 Iustin Pop
    except KeyError:
410 3ecf6786 Iustin Pop
      raise errors.TagError("Tag not found")
411 5c947f38 Iustin Pop
412 ff9c047c Iustin Pop
  def ToDict(self):
413 ff9c047c Iustin Pop
    """Taggable-object-specific conversion to standard python types.
414 ff9c047c Iustin Pop

415 ff9c047c Iustin Pop
    This replaces the tags set with a list.
416 ff9c047c Iustin Pop

417 ff9c047c Iustin Pop
    """
418 ff9c047c Iustin Pop
    bo = super(TaggableObject, self).ToDict()
419 ff9c047c Iustin Pop
420 ff9c047c Iustin Pop
    tags = bo.get("tags", None)
421 ff9c047c Iustin Pop
    if isinstance(tags, set):
422 ff9c047c Iustin Pop
      bo["tags"] = list(tags)
423 ff9c047c Iustin Pop
    return bo
424 ff9c047c Iustin Pop
425 ff9c047c Iustin Pop
  @classmethod
426 ff9c047c Iustin Pop
  def FromDict(cls, val):
427 ff9c047c Iustin Pop
    """Custom function for instances.
428 ff9c047c Iustin Pop

429 ff9c047c Iustin Pop
    """
430 ff9c047c Iustin Pop
    obj = super(TaggableObject, cls).FromDict(val)
431 ff9c047c Iustin Pop
    if hasattr(obj, "tags") and isinstance(obj.tags, list):
432 ff9c047c Iustin Pop
      obj.tags = set(obj.tags)
433 ff9c047c Iustin Pop
    return obj
434 ff9c047c Iustin Pop
435 5c947f38 Iustin Pop
436 061af273 Andrea Spadaccini
class MasterNetworkParameters(ConfigObject):
437 061af273 Andrea Spadaccini
  """Network configuration parameters for the master
438 061af273 Andrea Spadaccini

439 061af273 Andrea Spadaccini
  @ivar name: master name
440 061af273 Andrea Spadaccini
  @ivar ip: master IP
441 061af273 Andrea Spadaccini
  @ivar netmask: master netmask
442 061af273 Andrea Spadaccini
  @ivar netdev: master network device
443 061af273 Andrea Spadaccini
  @ivar ip_family: master IP family
444 061af273 Andrea Spadaccini

445 061af273 Andrea Spadaccini
  """
446 061af273 Andrea Spadaccini
  __slots__ = [
447 061af273 Andrea Spadaccini
    "name",
448 061af273 Andrea Spadaccini
    "ip",
449 061af273 Andrea Spadaccini
    "netmask",
450 061af273 Andrea Spadaccini
    "netdev",
451 061af273 Andrea Spadaccini
    "ip_family"
452 061af273 Andrea Spadaccini
    ]
453 061af273 Andrea Spadaccini
454 061af273 Andrea Spadaccini
455 a8083063 Iustin Pop
class ConfigData(ConfigObject):
456 a8083063 Iustin Pop
  """Top-level config object."""
457 3df43542 Guido Trotter
  __slots__ = [
458 3df43542 Guido Trotter
    "version",
459 3df43542 Guido Trotter
    "cluster",
460 3df43542 Guido Trotter
    "nodes",
461 3df43542 Guido Trotter
    "nodegroups",
462 3df43542 Guido Trotter
    "instances",
463 3df43542 Guido Trotter
    "serial_no",
464 3df43542 Guido Trotter
    ] + _TIMESTAMPS
465 a8083063 Iustin Pop
466 ff9c047c Iustin Pop
  def ToDict(self):
467 ff9c047c Iustin Pop
    """Custom function for top-level config data.
468 ff9c047c Iustin Pop

469 ff9c047c Iustin Pop
    This just replaces the list of instances, nodes and the cluster
470 ff9c047c Iustin Pop
    with standard python types.
471 ff9c047c Iustin Pop

472 ff9c047c Iustin Pop
    """
473 ff9c047c Iustin Pop
    mydict = super(ConfigData, self).ToDict()
474 ff9c047c Iustin Pop
    mydict["cluster"] = mydict["cluster"].ToDict()
475 3df43542 Guido Trotter
    for key in "nodes", "instances", "nodegroups":
476 ff9c047c Iustin Pop
      mydict[key] = self._ContainerToDicts(mydict[key])
477 ff9c047c Iustin Pop
478 ff9c047c Iustin Pop
    return mydict
479 ff9c047c Iustin Pop
480 ff9c047c Iustin Pop
  @classmethod
481 ff9c047c Iustin Pop
  def FromDict(cls, val):
482 ff9c047c Iustin Pop
    """Custom function for top-level config data
483 ff9c047c Iustin Pop

484 ff9c047c Iustin Pop
    """
485 ff9c047c Iustin Pop
    obj = super(ConfigData, cls).FromDict(val)
486 ff9c047c Iustin Pop
    obj.cluster = Cluster.FromDict(obj.cluster)
487 ff9c047c Iustin Pop
    obj.nodes = cls._ContainerFromDicts(obj.nodes, dict, Node)
488 ff9c047c Iustin Pop
    obj.instances = cls._ContainerFromDicts(obj.instances, dict, Instance)
489 3df43542 Guido Trotter
    obj.nodegroups = cls._ContainerFromDicts(obj.nodegroups, dict, NodeGroup)
490 ff9c047c Iustin Pop
    return obj
491 ff9c047c Iustin Pop
492 51cb1581 Luca Bigliardi
  def HasAnyDiskOfType(self, dev_type):
493 51cb1581 Luca Bigliardi
    """Check if in there is at disk of the given type in the configuration.
494 51cb1581 Luca Bigliardi

495 51cb1581 Luca Bigliardi
    @type dev_type: L{constants.LDS_BLOCK}
496 51cb1581 Luca Bigliardi
    @param dev_type: the type to look for
497 51cb1581 Luca Bigliardi
    @rtype: boolean
498 51cb1581 Luca Bigliardi
    @return: boolean indicating if a disk of the given type was found or not
499 51cb1581 Luca Bigliardi

500 51cb1581 Luca Bigliardi
    """
501 51cb1581 Luca Bigliardi
    for instance in self.instances.values():
502 51cb1581 Luca Bigliardi
      for disk in instance.disks:
503 51cb1581 Luca Bigliardi
        if disk.IsBasedOnDiskType(dev_type):
504 51cb1581 Luca Bigliardi
          return True
505 51cb1581 Luca Bigliardi
    return False
506 51cb1581 Luca Bigliardi
507 90d726a8 Iustin Pop
  def UpgradeConfig(self):
508 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
509 90d726a8 Iustin Pop

510 90d726a8 Iustin Pop
    """
511 90d726a8 Iustin Pop
    self.cluster.UpgradeConfig()
512 90d726a8 Iustin Pop
    for node in self.nodes.values():
513 90d726a8 Iustin Pop
      node.UpgradeConfig()
514 90d726a8 Iustin Pop
    for instance in self.instances.values():
515 90d726a8 Iustin Pop
      instance.UpgradeConfig()
516 3df43542 Guido Trotter
    if self.nodegroups is None:
517 3df43542 Guido Trotter
      self.nodegroups = {}
518 3df43542 Guido Trotter
    for nodegroup in self.nodegroups.values():
519 3df43542 Guido Trotter
      nodegroup.UpgradeConfig()
520 ee2f0ed4 Luca Bigliardi
    if self.cluster.drbd_usermode_helper is None:
521 ee2f0ed4 Luca Bigliardi
      # To decide if we set an helper let's check if at least one instance has
522 ee2f0ed4 Luca Bigliardi
      # a DRBD disk. This does not cover all the possible scenarios but it
523 ee2f0ed4 Luca Bigliardi
      # gives a good approximation.
524 ee2f0ed4 Luca Bigliardi
      if self.HasAnyDiskOfType(constants.LD_DRBD8):
525 ee2f0ed4 Luca Bigliardi
        self.cluster.drbd_usermode_helper = constants.DEFAULT_DRBD_HELPER
526 90d726a8 Iustin Pop
527 a8083063 Iustin Pop
528 a8083063 Iustin Pop
class NIC(ConfigObject):
529 a8083063 Iustin Pop
  """Config object representing a network card."""
530 1177d70e Guido Trotter
  __slots__ = ["mac", "ip", "nicparams"]
531 a8083063 Iustin Pop
532 255e19d4 Guido Trotter
  @classmethod
533 255e19d4 Guido Trotter
  def CheckParameterSyntax(cls, nicparams):
534 255e19d4 Guido Trotter
    """Check the given parameters for validity.
535 255e19d4 Guido Trotter

536 255e19d4 Guido Trotter
    @type nicparams:  dict
537 255e19d4 Guido Trotter
    @param nicparams: dictionary with parameter names/value
538 255e19d4 Guido Trotter
    @raise errors.ConfigurationError: when a parameter is not valid
539 255e19d4 Guido Trotter

540 255e19d4 Guido Trotter
    """
541 e8448672 Agata Murawska
    if (nicparams[constants.NIC_MODE] not in constants.NIC_VALID_MODES and
542 e8448672 Agata Murawska
        nicparams[constants.NIC_MODE] != constants.VALUE_AUTO):
543 255e19d4 Guido Trotter
      err = "Invalid nic mode: %s" % nicparams[constants.NIC_MODE]
544 255e19d4 Guido Trotter
      raise errors.ConfigurationError(err)
545 255e19d4 Guido Trotter
546 0c9d32c1 Guido Trotter
    if (nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED and
547 255e19d4 Guido Trotter
        not nicparams[constants.NIC_LINK]):
548 255e19d4 Guido Trotter
      err = "Missing bridged nic link"
549 255e19d4 Guido Trotter
      raise errors.ConfigurationError(err)
550 255e19d4 Guido Trotter
551 a8083063 Iustin Pop
552 a8083063 Iustin Pop
class Disk(ConfigObject):
553 a8083063 Iustin Pop
  """Config object representing a block device."""
554 a8083063 Iustin Pop
  __slots__ = ["dev_type", "logical_id", "physical_id",
555 bc5d0215 Andrea Spadaccini
               "children", "iv_name", "size", "mode", "params"]
556 a8083063 Iustin Pop
557 a8083063 Iustin Pop
  def CreateOnSecondary(self):
558 a8083063 Iustin Pop
    """Test if this device needs to be created on a secondary node."""
559 00fb8246 Michael Hanselmann
    return self.dev_type in (constants.LD_DRBD8, constants.LD_LV)
560 a8083063 Iustin Pop
561 a8083063 Iustin Pop
  def AssembleOnSecondary(self):
562 a8083063 Iustin Pop
    """Test if this device needs to be assembled on a secondary node."""
563 00fb8246 Michael Hanselmann
    return self.dev_type in (constants.LD_DRBD8, constants.LD_LV)
564 a8083063 Iustin Pop
565 a8083063 Iustin Pop
  def OpenOnSecondary(self):
566 a8083063 Iustin Pop
    """Test if this device needs to be opened on a secondary node."""
567 fe96220b Iustin Pop
    return self.dev_type in (constants.LD_LV,)
568 a8083063 Iustin Pop
569 222f2dd5 Iustin Pop
  def StaticDevPath(self):
570 222f2dd5 Iustin Pop
    """Return the device path if this device type has a static one.
571 222f2dd5 Iustin Pop

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

576 e51db2a6 Iustin Pop
    @warning: The path returned is not a normalized pathname; callers
577 e51db2a6 Iustin Pop
        should check that it is a valid path.
578 e51db2a6 Iustin Pop

579 222f2dd5 Iustin Pop
    """
580 222f2dd5 Iustin Pop
    if self.dev_type == constants.LD_LV:
581 222f2dd5 Iustin Pop
      return "/dev/%s/%s" % (self.logical_id[0], self.logical_id[1])
582 b6135bbc Apollon Oikonomopoulos
    elif self.dev_type == constants.LD_BLOCKDEV:
583 b6135bbc Apollon Oikonomopoulos
      return self.logical_id[1]
584 222f2dd5 Iustin Pop
    return None
585 222f2dd5 Iustin Pop
586 fc1dc9d7 Iustin Pop
  def ChildrenNeeded(self):
587 fc1dc9d7 Iustin Pop
    """Compute the needed number of children for activation.
588 fc1dc9d7 Iustin Pop

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

593 fc1dc9d7 Iustin Pop
    Currently, only DRBD8 supports diskless activation (therefore we
594 fc1dc9d7 Iustin Pop
    return 0), for all other we keep the previous semantics and return
595 fc1dc9d7 Iustin Pop
    -1.
596 fc1dc9d7 Iustin Pop

597 fc1dc9d7 Iustin Pop
    """
598 fc1dc9d7 Iustin Pop
    if self.dev_type == constants.LD_DRBD8:
599 fc1dc9d7 Iustin Pop
      return 0
600 fc1dc9d7 Iustin Pop
    return -1
601 fc1dc9d7 Iustin Pop
602 51cb1581 Luca Bigliardi
  def IsBasedOnDiskType(self, dev_type):
603 51cb1581 Luca Bigliardi
    """Check if the disk or its children are based on the given type.
604 51cb1581 Luca Bigliardi

605 51cb1581 Luca Bigliardi
    @type dev_type: L{constants.LDS_BLOCK}
606 51cb1581 Luca Bigliardi
    @param dev_type: the type to look for
607 51cb1581 Luca Bigliardi
    @rtype: boolean
608 51cb1581 Luca Bigliardi
    @return: boolean indicating if a device of the given type was found or not
609 51cb1581 Luca Bigliardi

610 51cb1581 Luca Bigliardi
    """
611 51cb1581 Luca Bigliardi
    if self.children:
612 51cb1581 Luca Bigliardi
      for child in self.children:
613 51cb1581 Luca Bigliardi
        if child.IsBasedOnDiskType(dev_type):
614 51cb1581 Luca Bigliardi
          return True
615 51cb1581 Luca Bigliardi
    return self.dev_type == dev_type
616 51cb1581 Luca Bigliardi
617 a8083063 Iustin Pop
  def GetNodes(self, node):
618 a8083063 Iustin Pop
    """This function returns the nodes this device lives on.
619 a8083063 Iustin Pop

620 a8083063 Iustin Pop
    Given the node on which the parent of the device lives on (or, in
621 a8083063 Iustin Pop
    case of a top-level device, the primary node of the devices'
622 a8083063 Iustin Pop
    instance), this function will return a list of nodes on which this
623 a8083063 Iustin Pop
    devices needs to (or can) be assembled.
624 a8083063 Iustin Pop

625 a8083063 Iustin Pop
    """
626 b6135bbc Apollon Oikonomopoulos
    if self.dev_type in [constants.LD_LV, constants.LD_FILE,
627 b6135bbc Apollon Oikonomopoulos
                         constants.LD_BLOCKDEV]:
628 a8083063 Iustin Pop
      result = [node]
629 a1f445d3 Iustin Pop
    elif self.dev_type in constants.LDS_DRBD:
630 a8083063 Iustin Pop
      result = [self.logical_id[0], self.logical_id[1]]
631 a8083063 Iustin Pop
      if node not in result:
632 3ecf6786 Iustin Pop
        raise errors.ConfigurationError("DRBD device passed unknown node")
633 a8083063 Iustin Pop
    else:
634 3ecf6786 Iustin Pop
      raise errors.ProgrammerError("Unhandled device type %s" % self.dev_type)
635 a8083063 Iustin Pop
    return result
636 a8083063 Iustin Pop
637 a8083063 Iustin Pop
  def ComputeNodeTree(self, parent_node):
638 a8083063 Iustin Pop
    """Compute the node/disk tree for this disk and its children.
639 a8083063 Iustin Pop

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

646 a8083063 Iustin Pop
    """
647 a8083063 Iustin Pop
    my_nodes = self.GetNodes(parent_node)
648 a8083063 Iustin Pop
    result = [(node, self) for node in my_nodes]
649 a8083063 Iustin Pop
    if not self.children:
650 a8083063 Iustin Pop
      # leaf device
651 a8083063 Iustin Pop
      return result
652 a8083063 Iustin Pop
    for node in my_nodes:
653 a8083063 Iustin Pop
      for child in self.children:
654 a8083063 Iustin Pop
        child_result = child.ComputeNodeTree(node)
655 a8083063 Iustin Pop
        if len(child_result) == 1:
656 a8083063 Iustin Pop
          # child (and all its descendants) is simple, doesn't split
657 a8083063 Iustin Pop
          # over multiple hosts, so we don't need to describe it, our
658 a8083063 Iustin Pop
          # own entry for this node describes it completely
659 a8083063 Iustin Pop
          continue
660 a8083063 Iustin Pop
        else:
661 a8083063 Iustin Pop
          # check if child nodes differ from my nodes; note that
662 a8083063 Iustin Pop
          # subdisk can differ from the child itself, and be instead
663 a8083063 Iustin Pop
          # one of its descendants
664 a8083063 Iustin Pop
          for subnode, subdisk in child_result:
665 a8083063 Iustin Pop
            if subnode not in my_nodes:
666 a8083063 Iustin Pop
              result.append((subnode, subdisk))
667 a8083063 Iustin Pop
            # otherwise child is under our own node, so we ignore this
668 a8083063 Iustin Pop
            # entry (but probably the other results in the list will
669 a8083063 Iustin Pop
            # be different)
670 a8083063 Iustin Pop
    return result
671 a8083063 Iustin Pop
672 6d33a6eb Iustin Pop
  def ComputeGrowth(self, amount):
673 6d33a6eb Iustin Pop
    """Compute the per-VG growth requirements.
674 6d33a6eb Iustin Pop

675 6d33a6eb Iustin Pop
    This only works for VG-based disks.
676 6d33a6eb Iustin Pop

677 6d33a6eb Iustin Pop
    @type amount: integer
678 6d33a6eb Iustin Pop
    @param amount: the desired increase in (user-visible) disk space
679 6d33a6eb Iustin Pop
    @rtype: dict
680 6d33a6eb Iustin Pop
    @return: a dictionary of volume-groups and the required size
681 6d33a6eb Iustin Pop

682 6d33a6eb Iustin Pop
    """
683 6d33a6eb Iustin Pop
    if self.dev_type == constants.LD_LV:
684 6d33a6eb Iustin Pop
      return {self.logical_id[0]: amount}
685 6d33a6eb Iustin Pop
    elif self.dev_type == constants.LD_DRBD8:
686 6d33a6eb Iustin Pop
      if self.children:
687 6d33a6eb Iustin Pop
        return self.children[0].ComputeGrowth(amount)
688 6d33a6eb Iustin Pop
      else:
689 6d33a6eb Iustin Pop
        return {}
690 6d33a6eb Iustin Pop
    else:
691 6d33a6eb Iustin Pop
      # Other disk types do not require VG space
692 6d33a6eb Iustin Pop
      return {}
693 6d33a6eb Iustin Pop
694 acec9d51 Iustin Pop
  def RecordGrow(self, amount):
695 acec9d51 Iustin Pop
    """Update the size of this disk after growth.
696 acec9d51 Iustin Pop

697 acec9d51 Iustin Pop
    This method recurses over the disks's children and updates their
698 acec9d51 Iustin Pop
    size correspondigly. The method needs to be kept in sync with the
699 acec9d51 Iustin Pop
    actual algorithms from bdev.
700 acec9d51 Iustin Pop

701 acec9d51 Iustin Pop
    """
702 4b97f902 Apollon Oikonomopoulos
    if self.dev_type in (constants.LD_LV, constants.LD_FILE):
703 acec9d51 Iustin Pop
      self.size += amount
704 acec9d51 Iustin Pop
    elif self.dev_type == constants.LD_DRBD8:
705 acec9d51 Iustin Pop
      if self.children:
706 acec9d51 Iustin Pop
        self.children[0].RecordGrow(amount)
707 acec9d51 Iustin Pop
      self.size += amount
708 acec9d51 Iustin Pop
    else:
709 acec9d51 Iustin Pop
      raise errors.ProgrammerError("Disk.RecordGrow called for unsupported"
710 acec9d51 Iustin Pop
                                   " disk type %s" % self.dev_type)
711 acec9d51 Iustin Pop
712 a805ec18 Iustin Pop
  def UnsetSize(self):
713 a805ec18 Iustin Pop
    """Sets recursively the size to zero for the disk and its children.
714 a805ec18 Iustin Pop

715 a805ec18 Iustin Pop
    """
716 a805ec18 Iustin Pop
    if self.children:
717 a805ec18 Iustin Pop
      for child in self.children:
718 a805ec18 Iustin Pop
        child.UnsetSize()
719 a805ec18 Iustin Pop
    self.size = 0
720 a805ec18 Iustin Pop
721 0402302c Iustin Pop
  def SetPhysicalID(self, target_node, nodes_ip):
722 0402302c Iustin Pop
    """Convert the logical ID to the physical ID.
723 0402302c Iustin Pop

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

726 0402302c Iustin Pop
    The routine descends down and updates its children also, because
727 0402302c Iustin Pop
    this helps when the only the top device is passed to the remote
728 0402302c Iustin Pop
    node.
729 0402302c Iustin Pop

730 0402302c Iustin Pop
    Arguments:
731 0402302c Iustin Pop
      - target_node: the node we wish to configure for
732 0402302c Iustin Pop
      - nodes_ip: a mapping of node name to ip
733 0402302c Iustin Pop

734 0402302c Iustin Pop
    The target_node must exist in in nodes_ip, and must be one of the
735 0402302c Iustin Pop
    nodes in the logical ID for each of the DRBD devices encountered
736 0402302c Iustin Pop
    in the disk tree.
737 0402302c Iustin Pop

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

768 ff9c047c Iustin Pop
    This replaces the children lists of objects with lists of
769 ff9c047c Iustin Pop
    standard python types.
770 ff9c047c Iustin Pop

771 ff9c047c Iustin Pop
    """
772 ff9c047c Iustin Pop
    bo = super(Disk, self).ToDict()
773 ff9c047c Iustin Pop
774 ff9c047c Iustin Pop
    for attr in ("children",):
775 ff9c047c Iustin Pop
      alist = bo.get(attr, None)
776 ff9c047c Iustin Pop
      if alist:
777 ff9c047c Iustin Pop
        bo[attr] = self._ContainerToDicts(alist)
778 ff9c047c Iustin Pop
    return bo
779 ff9c047c Iustin Pop
780 ff9c047c Iustin Pop
  @classmethod
781 ff9c047c Iustin Pop
  def FromDict(cls, val):
782 ff9c047c Iustin Pop
    """Custom function for Disks
783 ff9c047c Iustin Pop

784 ff9c047c Iustin Pop
    """
785 ff9c047c Iustin Pop
    obj = super(Disk, cls).FromDict(val)
786 ff9c047c Iustin Pop
    if obj.children:
787 ff9c047c Iustin Pop
      obj.children = cls._ContainerFromDicts(obj.children, list, Disk)
788 ff9c047c Iustin Pop
    if obj.logical_id and isinstance(obj.logical_id, list):
789 ff9c047c Iustin Pop
      obj.logical_id = tuple(obj.logical_id)
790 ff9c047c Iustin Pop
    if obj.physical_id and isinstance(obj.physical_id, list):
791 ff9c047c Iustin Pop
      obj.physical_id = tuple(obj.physical_id)
792 f9518d38 Iustin Pop
    if obj.dev_type in constants.LDS_DRBD:
793 f9518d38 Iustin Pop
      # we need a tuple of length six here
794 f9518d38 Iustin Pop
      if len(obj.logical_id) < 6:
795 f9518d38 Iustin Pop
        obj.logical_id += (None,) * (6 - len(obj.logical_id))
796 ff9c047c Iustin Pop
    return obj
797 ff9c047c Iustin Pop
798 65a15336 Iustin Pop
  def __str__(self):
799 65a15336 Iustin Pop
    """Custom str() formatter for disks.
800 65a15336 Iustin Pop

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

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

845 90d726a8 Iustin Pop
    """
846 90d726a8 Iustin Pop
    if self.children:
847 90d726a8 Iustin Pop
      for child in self.children:
848 90d726a8 Iustin Pop
        child.UpgradeConfig()
849 bc5d0215 Andrea Spadaccini
850 bc5d0215 Andrea Spadaccini
    if not self.params:
851 bc5d0215 Andrea Spadaccini
      self.params = constants.DISK_LD_DEFAULTS[self.dev_type].copy()
852 bc5d0215 Andrea Spadaccini
    else:
853 bc5d0215 Andrea Spadaccini
      self.params = FillDict(constants.DISK_LD_DEFAULTS[self.dev_type],
854 bc5d0215 Andrea Spadaccini
                             self.params)
855 90d726a8 Iustin Pop
    # add here config upgrade for this disk
856 90d726a8 Iustin Pop
857 a8083063 Iustin Pop
858 918eb80b Agata Murawska
class InstancePolicy(ConfigObject):
859 918eb80b Agata Murawska
  """Config object representing instance policy limits dictionary."""
860 918eb80b Agata Murawska
  __slots__ = ["min", "max", "std"]
861 918eb80b Agata Murawska
862 918eb80b Agata Murawska
  @classmethod
863 918eb80b Agata Murawska
  def CheckParameterSyntax(cls, ipolicy):
864 918eb80b Agata Murawska
    """ Check the instance policy for validity.
865 918eb80b Agata Murawska

866 918eb80b Agata Murawska
    """
867 918eb80b Agata Murawska
    for param in constants.ISPECS_PARAMETERS:
868 918eb80b Agata Murawska
      InstancePolicy.CheckISpecSyntax(ipolicy, param)
869 918eb80b Agata Murawska
870 918eb80b Agata Murawska
  @classmethod
871 918eb80b Agata Murawska
  def CheckISpecSyntax(cls, ipolicy, name):
872 918eb80b Agata Murawska
    """Check the instance policy for validity on a given key.
873 918eb80b Agata Murawska

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

877 918eb80b Agata Murawska
    @type ipolicy: dict
878 918eb80b Agata Murawska
    @param ipolicy: dictionary with min, max, std specs
879 918eb80b Agata Murawska
    @type name: string
880 918eb80b Agata Murawska
    @param name: what are the limits for
881 918eb80b Agata Murawska
    @raise errors.ConfigureError: when specs for given name are not valid
882 918eb80b Agata Murawska

883 918eb80b Agata Murawska
    """
884 4f725341 Agata Murawska
    min_v = ipolicy[constants.ISPECS_MIN].get(name, 0)
885 4f725341 Agata Murawska
    std_v = ipolicy[constants.ISPECS_STD].get(name, min_v)
886 4f725341 Agata Murawska
    max_v = ipolicy[constants.ISPECS_MAX].get(name, std_v)
887 918eb80b Agata Murawska
    err = ("Invalid specification of min/max/std values for %s: %s/%s/%s" %
888 918eb80b Agata Murawska
           (name,
889 4f725341 Agata Murawska
            ipolicy[constants.ISPECS_MIN].get(name, "-"),
890 4f725341 Agata Murawska
            ipolicy[constants.ISPECS_MAX].get(name, "-"),
891 4f725341 Agata Murawska
            ipolicy[constants.ISPECS_STD].get(name, "-")))
892 918eb80b Agata Murawska
    if min_v > std_v or std_v > max_v:
893 918eb80b Agata Murawska
      raise errors.ConfigurationError(err)
894 918eb80b Agata Murawska
895 918eb80b Agata Murawska
896 ec29fe40 Iustin Pop
class Instance(TaggableObject):
897 a8083063 Iustin Pop
  """Config object representing an instance."""
898 154b9580 Balazs Lecz
  __slots__ = [
899 a8083063 Iustin Pop
    "name",
900 a8083063 Iustin Pop
    "primary_node",
901 a8083063 Iustin Pop
    "os",
902 e69d05fd Iustin Pop
    "hypervisor",
903 5bf7b5cf Iustin Pop
    "hvparams",
904 5bf7b5cf Iustin Pop
    "beparams",
905 1bdcbbab Iustin Pop
    "osparams",
906 9ca8a7c5 Agata Murawska
    "admin_state",
907 a8083063 Iustin Pop
    "nics",
908 a8083063 Iustin Pop
    "disks",
909 a8083063 Iustin Pop
    "disk_template",
910 58acb49d Alexander Schreiber
    "network_port",
911 be1fa613 Iustin Pop
    "serial_no",
912 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
913 a8083063 Iustin Pop
914 a8083063 Iustin Pop
  def _ComputeSecondaryNodes(self):
915 a8083063 Iustin Pop
    """Compute the list of secondary nodes.
916 a8083063 Iustin Pop

917 cfcc5c6d Iustin Pop
    This is a simple wrapper over _ComputeAllNodes.
918 cfcc5c6d Iustin Pop

919 cfcc5c6d Iustin Pop
    """
920 cfcc5c6d Iustin Pop
    all_nodes = set(self._ComputeAllNodes())
921 cfcc5c6d Iustin Pop
    all_nodes.discard(self.primary_node)
922 cfcc5c6d Iustin Pop
    return tuple(all_nodes)
923 cfcc5c6d Iustin Pop
924 cfcc5c6d Iustin Pop
  secondary_nodes = property(_ComputeSecondaryNodes, None, None,
925 cfcc5c6d Iustin Pop
                             "List of secondary nodes")
926 cfcc5c6d Iustin Pop
927 cfcc5c6d Iustin Pop
  def _ComputeAllNodes(self):
928 cfcc5c6d Iustin Pop
    """Compute the list of all nodes.
929 cfcc5c6d Iustin Pop

930 a8083063 Iustin Pop
    Since the data is already there (in the drbd disks), keeping it as
931 a8083063 Iustin Pop
    a separate normal attribute is redundant and if not properly
932 a8083063 Iustin Pop
    synchronised can cause problems. Thus it's better to compute it
933 a8083063 Iustin Pop
    dynamically.
934 a8083063 Iustin Pop

935 a8083063 Iustin Pop
    """
936 cfcc5c6d Iustin Pop
    def _Helper(nodes, device):
937 cfcc5c6d Iustin Pop
      """Recursively computes nodes given a top device."""
938 a1f445d3 Iustin Pop
      if device.dev_type in constants.LDS_DRBD:
939 cfcc5c6d Iustin Pop
        nodea, nodeb = device.logical_id[:2]
940 cfcc5c6d Iustin Pop
        nodes.add(nodea)
941 cfcc5c6d Iustin Pop
        nodes.add(nodeb)
942 a8083063 Iustin Pop
      if device.children:
943 a8083063 Iustin Pop
        for child in device.children:
944 cfcc5c6d Iustin Pop
          _Helper(nodes, child)
945 a8083063 Iustin Pop
946 cfcc5c6d Iustin Pop
    all_nodes = set()
947 99c7b2a1 Iustin Pop
    all_nodes.add(self.primary_node)
948 a8083063 Iustin Pop
    for device in self.disks:
949 cfcc5c6d Iustin Pop
      _Helper(all_nodes, device)
950 cfcc5c6d Iustin Pop
    return tuple(all_nodes)
951 a8083063 Iustin Pop
952 cfcc5c6d Iustin Pop
  all_nodes = property(_ComputeAllNodes, None, None,
953 cfcc5c6d Iustin Pop
                       "List of all nodes of the instance")
954 a8083063 Iustin Pop
955 a8083063 Iustin Pop
  def MapLVsByNode(self, lvmap=None, devs=None, node=None):
956 a8083063 Iustin Pop
    """Provide a mapping of nodes to LVs this instance owns.
957 a8083063 Iustin Pop

958 c41eea6e Iustin Pop
    This function figures out what logical volumes should belong on
959 c41eea6e Iustin Pop
    which nodes, recursing through a device tree.
960 a8083063 Iustin Pop

961 c41eea6e Iustin Pop
    @param lvmap: optional dictionary to receive the
962 c41eea6e Iustin Pop
        'node' : ['lv', ...] data.
963 a8083063 Iustin Pop

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

969 a8083063 Iustin Pop
    """
970 a8083063 Iustin Pop
    if node == None:
971 a8083063 Iustin Pop
      node = self.primary_node
972 a8083063 Iustin Pop
973 a8083063 Iustin Pop
    if lvmap is None:
974 e687ec01 Michael Hanselmann
      lvmap = {
975 e687ec01 Michael Hanselmann
        node: [],
976 e687ec01 Michael Hanselmann
        }
977 a8083063 Iustin Pop
      ret = lvmap
978 a8083063 Iustin Pop
    else:
979 a8083063 Iustin Pop
      if not node in lvmap:
980 a8083063 Iustin Pop
        lvmap[node] = []
981 a8083063 Iustin Pop
      ret = None
982 a8083063 Iustin Pop
983 a8083063 Iustin Pop
    if not devs:
984 a8083063 Iustin Pop
      devs = self.disks
985 a8083063 Iustin Pop
986 a8083063 Iustin Pop
    for dev in devs:
987 fe96220b Iustin Pop
      if dev.dev_type == constants.LD_LV:
988 e687ec01 Michael Hanselmann
        lvmap[node].append(dev.logical_id[0] + "/" + dev.logical_id[1])
989 a8083063 Iustin Pop
990 a1f445d3 Iustin Pop
      elif dev.dev_type in constants.LDS_DRBD:
991 a8083063 Iustin Pop
        if dev.children:
992 a8083063 Iustin Pop
          self.MapLVsByNode(lvmap, dev.children, dev.logical_id[0])
993 a8083063 Iustin Pop
          self.MapLVsByNode(lvmap, dev.children, dev.logical_id[1])
994 a8083063 Iustin Pop
995 a8083063 Iustin Pop
      elif dev.children:
996 a8083063 Iustin Pop
        self.MapLVsByNode(lvmap, dev.children, node)
997 a8083063 Iustin Pop
998 a8083063 Iustin Pop
    return ret
999 a8083063 Iustin Pop
1000 ad24e046 Iustin Pop
  def FindDisk(self, idx):
1001 ad24e046 Iustin Pop
    """Find a disk given having a specified index.
1002 644eeef9 Iustin Pop

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

1005 ad24e046 Iustin Pop
    @type idx: int
1006 ad24e046 Iustin Pop
    @param idx: the disk index
1007 ad24e046 Iustin Pop
    @rtype: L{Disk}
1008 ad24e046 Iustin Pop
    @return: the corresponding disk
1009 ad24e046 Iustin Pop
    @raise errors.OpPrereqError: when the given index is not valid
1010 644eeef9 Iustin Pop

1011 ad24e046 Iustin Pop
    """
1012 ad24e046 Iustin Pop
    try:
1013 ad24e046 Iustin Pop
      idx = int(idx)
1014 ad24e046 Iustin Pop
      return self.disks[idx]
1015 691744c4 Iustin Pop
    except (TypeError, ValueError), err:
1016 debac808 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index: '%s'" % str(err),
1017 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
1018 ad24e046 Iustin Pop
    except IndexError:
1019 ad24e046 Iustin Pop
      raise errors.OpPrereqError("Invalid disk index: %d (instace has disks"
1020 daa55b04 Michael Hanselmann
                                 " 0 to %d" % (idx, len(self.disks) - 1),
1021 debac808 Iustin Pop
                                 errors.ECODE_INVAL)
1022 644eeef9 Iustin Pop
1023 ff9c047c Iustin Pop
  def ToDict(self):
1024 ff9c047c Iustin Pop
    """Instance-specific conversion to standard python types.
1025 ff9c047c Iustin Pop

1026 ff9c047c Iustin Pop
    This replaces the children lists of objects with lists of standard
1027 ff9c047c Iustin Pop
    python types.
1028 ff9c047c Iustin Pop

1029 ff9c047c Iustin Pop
    """
1030 ff9c047c Iustin Pop
    bo = super(Instance, self).ToDict()
1031 ff9c047c Iustin Pop
1032 ff9c047c Iustin Pop
    for attr in "nics", "disks":
1033 ff9c047c Iustin Pop
      alist = bo.get(attr, None)
1034 ff9c047c Iustin Pop
      if alist:
1035 ff9c047c Iustin Pop
        nlist = self._ContainerToDicts(alist)
1036 ff9c047c Iustin Pop
      else:
1037 ff9c047c Iustin Pop
        nlist = []
1038 ff9c047c Iustin Pop
      bo[attr] = nlist
1039 ff9c047c Iustin Pop
    return bo
1040 ff9c047c Iustin Pop
1041 ff9c047c Iustin Pop
  @classmethod
1042 ff9c047c Iustin Pop
  def FromDict(cls, val):
1043 ff9c047c Iustin Pop
    """Custom function for instances.
1044 ff9c047c Iustin Pop

1045 ff9c047c Iustin Pop
    """
1046 9ca8a7c5 Agata Murawska
    if "admin_state" not in val:
1047 9ca8a7c5 Agata Murawska
      if val.get("admin_up", False):
1048 9ca8a7c5 Agata Murawska
        val["admin_state"] = constants.ADMINST_UP
1049 9ca8a7c5 Agata Murawska
      else:
1050 9ca8a7c5 Agata Murawska
        val["admin_state"] = constants.ADMINST_DOWN
1051 9ca8a7c5 Agata Murawska
    if "admin_up" in val:
1052 9ca8a7c5 Agata Murawska
      del val["admin_up"]
1053 ff9c047c Iustin Pop
    obj = super(Instance, cls).FromDict(val)
1054 ff9c047c Iustin Pop
    obj.nics = cls._ContainerFromDicts(obj.nics, list, NIC)
1055 ff9c047c Iustin Pop
    obj.disks = cls._ContainerFromDicts(obj.disks, list, Disk)
1056 ff9c047c Iustin Pop
    return obj
1057 ff9c047c Iustin Pop
1058 90d726a8 Iustin Pop
  def UpgradeConfig(self):
1059 90d726a8 Iustin Pop
    """Fill defaults for missing configuration values.
1060 90d726a8 Iustin Pop

1061 90d726a8 Iustin Pop
    """
1062 90d726a8 Iustin Pop
    for nic in self.nics:
1063 90d726a8 Iustin Pop
      nic.UpgradeConfig()
1064 90d726a8 Iustin Pop
    for disk in self.disks:
1065 90d726a8 Iustin Pop
      disk.UpgradeConfig()
1066 7736a5f2 Iustin Pop
    if self.hvparams:
1067 7736a5f2 Iustin Pop
      for key in constants.HVC_GLOBALS:
1068 7736a5f2 Iustin Pop
        try:
1069 7736a5f2 Iustin Pop
          del self.hvparams[key]
1070 7736a5f2 Iustin Pop
        except KeyError:
1071 7736a5f2 Iustin Pop
          pass
1072 1bdcbbab Iustin Pop
    if self.osparams is None:
1073 1bdcbbab Iustin Pop
      self.osparams = {}
1074 8c72ab2b Guido Trotter
    UpgradeBeParams(self.beparams)
1075 90d726a8 Iustin Pop
1076 a8083063 Iustin Pop
1077 a8083063 Iustin Pop
class OS(ConfigObject):
1078 b41b3516 Iustin Pop
  """Config object representing an operating system.
1079 b41b3516 Iustin Pop

1080 b41b3516 Iustin Pop
  @type supported_parameters: list
1081 b41b3516 Iustin Pop
  @ivar supported_parameters: a list of tuples, name and description,
1082 b41b3516 Iustin Pop
      containing the supported parameters by this OS
1083 b41b3516 Iustin Pop

1084 870dc44c Iustin Pop
  @type VARIANT_DELIM: string
1085 870dc44c Iustin Pop
  @cvar VARIANT_DELIM: the variant delimiter
1086 870dc44c Iustin Pop

1087 b41b3516 Iustin Pop
  """
1088 a8083063 Iustin Pop
  __slots__ = [
1089 a8083063 Iustin Pop
    "name",
1090 a8083063 Iustin Pop
    "path",
1091 082a7f91 Guido Trotter
    "api_versions",
1092 a8083063 Iustin Pop
    "create_script",
1093 a8083063 Iustin Pop
    "export_script",
1094 386b57af Iustin Pop
    "import_script",
1095 386b57af Iustin Pop
    "rename_script",
1096 b41b3516 Iustin Pop
    "verify_script",
1097 6d79896b Guido Trotter
    "supported_variants",
1098 b41b3516 Iustin Pop
    "supported_parameters",
1099 a8083063 Iustin Pop
    ]
1100 a8083063 Iustin Pop
1101 870dc44c Iustin Pop
  VARIANT_DELIM = "+"
1102 870dc44c Iustin Pop
1103 870dc44c Iustin Pop
  @classmethod
1104 870dc44c Iustin Pop
  def SplitNameVariant(cls, name):
1105 870dc44c Iustin Pop
    """Splits the name into the proper name and variant.
1106 870dc44c Iustin Pop

1107 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
1108 870dc44c Iustin Pop
    @rtype: list
1109 870dc44c Iustin Pop
    @return: a list of two elements; if the original name didn't
1110 870dc44c Iustin Pop
        contain a variant, it's returned as an empty string
1111 870dc44c Iustin Pop

1112 870dc44c Iustin Pop
    """
1113 870dc44c Iustin Pop
    nv = name.split(cls.VARIANT_DELIM, 1)
1114 870dc44c Iustin Pop
    if len(nv) == 1:
1115 870dc44c Iustin Pop
      nv.append("")
1116 870dc44c Iustin Pop
    return nv
1117 870dc44c Iustin Pop
1118 870dc44c Iustin Pop
  @classmethod
1119 870dc44c Iustin Pop
  def GetName(cls, name):
1120 870dc44c Iustin Pop
    """Returns the proper name of the os (without the variant).
1121 870dc44c Iustin Pop

1122 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
1123 870dc44c Iustin Pop

1124 870dc44c Iustin Pop
    """
1125 870dc44c Iustin Pop
    return cls.SplitNameVariant(name)[0]
1126 870dc44c Iustin Pop
1127 870dc44c Iustin Pop
  @classmethod
1128 870dc44c Iustin Pop
  def GetVariant(cls, name):
1129 870dc44c Iustin Pop
    """Returns the variant the os (without the base name).
1130 870dc44c Iustin Pop

1131 870dc44c Iustin Pop
    @param name: the OS (unprocessed) name
1132 870dc44c Iustin Pop

1133 870dc44c Iustin Pop
    """
1134 870dc44c Iustin Pop
    return cls.SplitNameVariant(name)[1]
1135 870dc44c Iustin Pop
1136 7c0d6283 Michael Hanselmann
1137 5f06ce5e Michael Hanselmann
class NodeHvState(ConfigObject):
1138 5f06ce5e Michael Hanselmann
  """Hypvervisor state on a node.
1139 5f06ce5e Michael Hanselmann

1140 5f06ce5e Michael Hanselmann
  @ivar mem_total: Total amount of memory
1141 5f06ce5e Michael Hanselmann
  @ivar mem_node: Memory used by, or reserved for, the node itself (not always
1142 5f06ce5e Michael Hanselmann
    available)
1143 5f06ce5e Michael Hanselmann
  @ivar mem_hv: Memory used by hypervisor or lost due to instance allocation
1144 5f06ce5e Michael Hanselmann
    rounding
1145 5f06ce5e Michael Hanselmann
  @ivar mem_inst: Memory used by instances living on node
1146 5f06ce5e Michael Hanselmann
  @ivar cpu_total: Total node CPU core count
1147 5f06ce5e Michael Hanselmann
  @ivar cpu_node: Number of CPU cores reserved for the node itself
1148 5f06ce5e Michael Hanselmann

1149 5f06ce5e Michael Hanselmann
  """
1150 5f06ce5e Michael Hanselmann
  __slots__ = [
1151 5f06ce5e Michael Hanselmann
    "mem_total",
1152 5f06ce5e Michael Hanselmann
    "mem_node",
1153 5f06ce5e Michael Hanselmann
    "mem_hv",
1154 5f06ce5e Michael Hanselmann
    "mem_inst",
1155 5f06ce5e Michael Hanselmann
    "cpu_total",
1156 5f06ce5e Michael Hanselmann
    "cpu_node",
1157 5f06ce5e Michael Hanselmann
    ] + _TIMESTAMPS
1158 5f06ce5e Michael Hanselmann
1159 5f06ce5e Michael Hanselmann
1160 5f06ce5e Michael Hanselmann
class NodeDiskState(ConfigObject):
1161 5f06ce5e Michael Hanselmann
  """Disk state on a node.
1162 5f06ce5e Michael Hanselmann

1163 5f06ce5e Michael Hanselmann
  """
1164 5f06ce5e Michael Hanselmann
  __slots__ = [
1165 5f06ce5e Michael Hanselmann
    "total",
1166 5f06ce5e Michael Hanselmann
    "reserved",
1167 5f06ce5e Michael Hanselmann
    "overhead",
1168 5f06ce5e Michael Hanselmann
    ] + _TIMESTAMPS
1169 5f06ce5e Michael Hanselmann
1170 5f06ce5e Michael Hanselmann
1171 ec29fe40 Iustin Pop
class Node(TaggableObject):
1172 634d30f4 Michael Hanselmann
  """Config object representing a node.
1173 634d30f4 Michael Hanselmann

1174 634d30f4 Michael Hanselmann
  @ivar hv_state: Hypervisor state (e.g. number of CPUs)
1175 634d30f4 Michael Hanselmann
  @ivar hv_state_static: Hypervisor state overriden by user
1176 634d30f4 Michael Hanselmann
  @ivar disk_state: Disk state (e.g. free space)
1177 634d30f4 Michael Hanselmann
  @ivar disk_state_static: Disk state overriden by user
1178 634d30f4 Michael Hanselmann

1179 634d30f4 Michael Hanselmann
  """
1180 154b9580 Balazs Lecz
  __slots__ = [
1181 ec29fe40 Iustin Pop
    "name",
1182 ec29fe40 Iustin Pop
    "primary_ip",
1183 ec29fe40 Iustin Pop
    "secondary_ip",
1184 be1fa613 Iustin Pop
    "serial_no",
1185 8b8b8b81 Iustin Pop
    "master_candidate",
1186 fc0fe88c Iustin Pop
    "offline",
1187 af64c0ea Iustin Pop
    "drained",
1188 f936c153 Iustin Pop
    "group",
1189 490acd18 Iustin Pop
    "master_capable",
1190 490acd18 Iustin Pop
    "vm_capable",
1191 095e71aa Renรฉ Nussbaumer
    "ndparams",
1192 25124d4a Renรฉ Nussbaumer
    "powered",
1193 5b49ed09 Renรฉ Nussbaumer
    "hv_state",
1194 634d30f4 Michael Hanselmann
    "hv_state_static",
1195 5b49ed09 Renรฉ Nussbaumer
    "disk_state",
1196 634d30f4 Michael Hanselmann
    "disk_state_static",
1197 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
1198 a8083063 Iustin Pop
1199 490acd18 Iustin Pop
  def UpgradeConfig(self):
1200 490acd18 Iustin Pop
    """Fill defaults for missing configuration values.
1201 490acd18 Iustin Pop

1202 490acd18 Iustin Pop
    """
1203 b459a848 Andrea Spadaccini
    # pylint: disable=E0203
1204 490acd18 Iustin Pop
    # because these are "defined" via slots, not manually
1205 490acd18 Iustin Pop
    if self.master_capable is None:
1206 490acd18 Iustin Pop
      self.master_capable = True
1207 490acd18 Iustin Pop
1208 490acd18 Iustin Pop
    if self.vm_capable is None:
1209 490acd18 Iustin Pop
      self.vm_capable = True
1210 490acd18 Iustin Pop
1211 095e71aa Renรฉ Nussbaumer
    if self.ndparams is None:
1212 095e71aa Renรฉ Nussbaumer
      self.ndparams = {}
1213 095e71aa Renรฉ Nussbaumer
1214 25124d4a Renรฉ Nussbaumer
    if self.powered is None:
1215 25124d4a Renรฉ Nussbaumer
      self.powered = True
1216 25124d4a Renรฉ Nussbaumer
1217 5f06ce5e Michael Hanselmann
  def ToDict(self):
1218 5f06ce5e Michael Hanselmann
    """Custom function for serializing.
1219 5f06ce5e Michael Hanselmann

1220 5f06ce5e Michael Hanselmann
    """
1221 5f06ce5e Michael Hanselmann
    data = super(Node, self).ToDict()
1222 5f06ce5e Michael Hanselmann
1223 5f06ce5e Michael Hanselmann
    hv_state = data.get("hv_state", None)
1224 5f06ce5e Michael Hanselmann
    if hv_state is not None:
1225 5f06ce5e Michael Hanselmann
      data["hv_state"] = self._ContainerToDicts(hv_state)
1226 5f06ce5e Michael Hanselmann
1227 5f06ce5e Michael Hanselmann
    disk_state = data.get("disk_state", None)
1228 5f06ce5e Michael Hanselmann
    if disk_state is not None:
1229 5f06ce5e Michael Hanselmann
      data["disk_state"] = \
1230 5f06ce5e Michael Hanselmann
        dict((key, self._ContainerToDicts(value))
1231 5f06ce5e Michael Hanselmann
             for (key, value) in disk_state.items())
1232 5f06ce5e Michael Hanselmann
1233 5f06ce5e Michael Hanselmann
    return data
1234 5f06ce5e Michael Hanselmann
1235 5f06ce5e Michael Hanselmann
  @classmethod
1236 5f06ce5e Michael Hanselmann
  def FromDict(cls, val):
1237 5f06ce5e Michael Hanselmann
    """Custom function for deserializing.
1238 5f06ce5e Michael Hanselmann

1239 5f06ce5e Michael Hanselmann
    """
1240 5f06ce5e Michael Hanselmann
    obj = super(Node, cls).FromDict(val)
1241 5f06ce5e Michael Hanselmann
1242 5f06ce5e Michael Hanselmann
    if obj.hv_state is not None:
1243 5f06ce5e Michael Hanselmann
      obj.hv_state = cls._ContainerFromDicts(obj.hv_state, dict, NodeHvState)
1244 5f06ce5e Michael Hanselmann
1245 5f06ce5e Michael Hanselmann
    if obj.disk_state is not None:
1246 5f06ce5e Michael Hanselmann
      obj.disk_state = \
1247 5f06ce5e Michael Hanselmann
        dict((key, cls._ContainerFromDicts(value, dict, NodeDiskState))
1248 5f06ce5e Michael Hanselmann
             for (key, value) in obj.disk_state.items())
1249 5f06ce5e Michael Hanselmann
1250 5f06ce5e Michael Hanselmann
    return obj
1251 5f06ce5e Michael Hanselmann
1252 a8083063 Iustin Pop
1253 1ffd2673 Michael Hanselmann
class NodeGroup(TaggableObject):
1254 24a3707f Guido Trotter
  """Config object representing a node group."""
1255 24a3707f Guido Trotter
  __slots__ = [
1256 24a3707f Guido Trotter
    "name",
1257 24a3707f Guido Trotter
    "members",
1258 095e71aa Renรฉ Nussbaumer
    "ndparams",
1259 bc5d0215 Andrea Spadaccini
    "diskparams",
1260 81e3ab4f Agata Murawska
    "ipolicy",
1261 e11a1b77 Adeodato Simo
    "serial_no",
1262 a8282327 Renรฉ Nussbaumer
    "hv_state_static",
1263 a8282327 Renรฉ Nussbaumer
    "disk_state_static",
1264 90e99856 Adeodato Simo
    "alloc_policy",
1265 24a3707f Guido Trotter
    ] + _TIMESTAMPS + _UUID
1266 24a3707f Guido Trotter
1267 24a3707f Guido Trotter
  def ToDict(self):
1268 24a3707f Guido Trotter
    """Custom function for nodegroup.
1269 24a3707f Guido Trotter

1270 c60abd62 Guido Trotter
    This discards the members object, which gets recalculated and is only kept
1271 c60abd62 Guido Trotter
    in memory.
1272 24a3707f Guido Trotter

1273 24a3707f Guido Trotter
    """
1274 24a3707f Guido Trotter
    mydict = super(NodeGroup, self).ToDict()
1275 24a3707f Guido Trotter
    del mydict["members"]
1276 24a3707f Guido Trotter
    return mydict
1277 24a3707f Guido Trotter
1278 24a3707f Guido Trotter
  @classmethod
1279 24a3707f Guido Trotter
  def FromDict(cls, val):
1280 24a3707f Guido Trotter
    """Custom function for nodegroup.
1281 24a3707f Guido Trotter

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

1284 24a3707f Guido Trotter
    """
1285 24a3707f Guido Trotter
    obj = super(NodeGroup, cls).FromDict(val)
1286 24a3707f Guido Trotter
    obj.members = []
1287 24a3707f Guido Trotter
    return obj
1288 24a3707f Guido Trotter
1289 095e71aa Renรฉ Nussbaumer
  def UpgradeConfig(self):
1290 095e71aa Renรฉ Nussbaumer
    """Fill defaults for missing configuration values.
1291 095e71aa Renรฉ Nussbaumer

1292 095e71aa Renรฉ Nussbaumer
    """
1293 095e71aa Renรฉ Nussbaumer
    if self.ndparams is None:
1294 095e71aa Renรฉ Nussbaumer
      self.ndparams = {}
1295 095e71aa Renรฉ Nussbaumer
1296 e11a1b77 Adeodato Simo
    if self.serial_no is None:
1297 e11a1b77 Adeodato Simo
      self.serial_no = 1
1298 e11a1b77 Adeodato Simo
1299 90e99856 Adeodato Simo
    if self.alloc_policy is None:
1300 90e99856 Adeodato Simo
      self.alloc_policy = constants.ALLOC_POLICY_PREFERRED
1301 90e99856 Adeodato Simo
1302 e11a1b77 Adeodato Simo
    # We only update mtime, and not ctime, since we would not be able to provide
1303 e11a1b77 Adeodato Simo
    # a correct value for creation time.
1304 e11a1b77 Adeodato Simo
    if self.mtime is None:
1305 e11a1b77 Adeodato Simo
      self.mtime = time.time()
1306 e11a1b77 Adeodato Simo
1307 bc5d0215 Andrea Spadaccini
    self.diskparams = UpgradeDiskParams(self.diskparams)
1308 81e3ab4f Agata Murawska
    if self.ipolicy is None:
1309 81e3ab4f Agata Murawska
      self.ipolicy = MakeEmptyIPolicy()
1310 bc5d0215 Andrea Spadaccini
1311 095e71aa Renรฉ Nussbaumer
  def FillND(self, node):
1312 ce523de1 Michael Hanselmann
    """Return filled out ndparams for L{objects.Node}
1313 095e71aa Renรฉ Nussbaumer

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

1318 095e71aa Renรฉ Nussbaumer
    """
1319 095e71aa Renรฉ Nussbaumer
    return self.SimpleFillND(node.ndparams)
1320 095e71aa Renรฉ Nussbaumer
1321 095e71aa Renรฉ Nussbaumer
  def SimpleFillND(self, ndparams):
1322 095e71aa Renรฉ Nussbaumer
    """Fill a given ndparams dict with defaults.
1323 095e71aa Renรฉ Nussbaumer

1324 095e71aa Renรฉ Nussbaumer
    @type ndparams: dict
1325 095e71aa Renรฉ Nussbaumer
    @param ndparams: the dict to fill
1326 095e71aa Renรฉ Nussbaumer
    @rtype: dict
1327 095e71aa Renรฉ Nussbaumer
    @return: a copy of the passed in ndparams with missing keys filled
1328 e6e88de6 Adeodato Simo
        from the node group defaults
1329 095e71aa Renรฉ Nussbaumer

1330 095e71aa Renรฉ Nussbaumer
    """
1331 095e71aa Renรฉ Nussbaumer
    return FillDict(self.ndparams, ndparams)
1332 095e71aa Renรฉ Nussbaumer
1333 24a3707f Guido Trotter
1334 ec29fe40 Iustin Pop
class Cluster(TaggableObject):
1335 a8083063 Iustin Pop
  """Config object representing the cluster."""
1336 154b9580 Balazs Lecz
  __slots__ = [
1337 a8083063 Iustin Pop
    "serial_no",
1338 a8083063 Iustin Pop
    "rsahostkeypub",
1339 a8083063 Iustin Pop
    "highest_used_port",
1340 b2fddf63 Iustin Pop
    "tcpudp_port_pool",
1341 a8083063 Iustin Pop
    "mac_prefix",
1342 a8083063 Iustin Pop
    "volume_group_name",
1343 999b183c Iustin Pop
    "reserved_lvs",
1344 9e33896b Luca Bigliardi
    "drbd_usermode_helper",
1345 a8083063 Iustin Pop
    "default_bridge",
1346 02691904 Alexander Schreiber
    "default_hypervisor",
1347 f6bd6e98 Michael Hanselmann
    "master_node",
1348 f6bd6e98 Michael Hanselmann
    "master_ip",
1349 f6bd6e98 Michael Hanselmann
    "master_netdev",
1350 5a8648eb Andrea Spadaccini
    "master_netmask",
1351 33be7576 Andrea Spadaccini
    "use_external_mip_script",
1352 f6bd6e98 Michael Hanselmann
    "cluster_name",
1353 f6bd6e98 Michael Hanselmann
    "file_storage_dir",
1354 4b97f902 Apollon Oikonomopoulos
    "shared_file_storage_dir",
1355 e69d05fd Iustin Pop
    "enabled_hypervisors",
1356 5bf7b5cf Iustin Pop
    "hvparams",
1357 918eb80b Agata Murawska
    "ipolicy",
1358 17463d22 Renรฉ Nussbaumer
    "os_hvp",
1359 5bf7b5cf Iustin Pop
    "beparams",
1360 1bdcbbab Iustin Pop
    "osparams",
1361 c8fcde47 Guido Trotter
    "nicparams",
1362 095e71aa Renรฉ Nussbaumer
    "ndparams",
1363 bc5d0215 Andrea Spadaccini
    "diskparams",
1364 4b7735f9 Iustin Pop
    "candidate_pool_size",
1365 b86a6bcd Guido Trotter
    "modify_etc_hosts",
1366 b989b9d9 Ken Wehr
    "modify_ssh_setup",
1367 3953242f Iustin Pop
    "maintain_node_health",
1368 4437d889 Balazs Lecz
    "uid_pool",
1369 bf4af505 Apollon Oikonomopoulos
    "default_iallocator",
1370 87b2cd45 Iustin Pop
    "hidden_os",
1371 87b2cd45 Iustin Pop
    "blacklisted_os",
1372 2f20d07b Manuel Franceschini
    "primary_ip_family",
1373 3d914585 Renรฉ Nussbaumer
    "prealloc_wipe_disks",
1374 2da9f556 Renรฉ Nussbaumer
    "hv_state_static",
1375 2da9f556 Renรฉ Nussbaumer
    "disk_state_static",
1376 e1dcc53a Iustin Pop
    ] + _TIMESTAMPS + _UUID
1377 a8083063 Iustin Pop
1378 b86a6bcd Guido Trotter
  def UpgradeConfig(self):
1379 b86a6bcd Guido Trotter
    """Fill defaults for missing configuration values.
1380 b86a6bcd Guido Trotter

1381 b86a6bcd Guido Trotter
    """
1382 b459a848 Andrea Spadaccini
    # pylint: disable=E0203
1383 fe267188 Iustin Pop
    # because these are "defined" via slots, not manually
1384 c1b42c18 Guido Trotter
    if self.hvparams is None:
1385 c1b42c18 Guido Trotter
      self.hvparams = constants.HVC_DEFAULTS
1386 c1b42c18 Guido Trotter
    else:
1387 c1b42c18 Guido Trotter
      for hypervisor in self.hvparams:
1388 abe609b2 Guido Trotter
        self.hvparams[hypervisor] = FillDict(
1389 c1b42c18 Guido Trotter
            constants.HVC_DEFAULTS[hypervisor], self.hvparams[hypervisor])
1390 c1b42c18 Guido Trotter
1391 17463d22 Renรฉ Nussbaumer
    if self.os_hvp is None:
1392 17463d22 Renรฉ Nussbaumer
      self.os_hvp = {}
1393 17463d22 Renรฉ Nussbaumer
1394 1bdcbbab Iustin Pop
    # osparams added before 2.2
1395 1bdcbbab Iustin Pop
    if self.osparams is None:
1396 1bdcbbab Iustin Pop
      self.osparams = {}
1397 1bdcbbab Iustin Pop
1398 095e71aa Renรฉ Nussbaumer
    if self.ndparams is None:
1399 095e71aa Renรฉ Nussbaumer
      self.ndparams = constants.NDC_DEFAULTS
1400 095e71aa Renรฉ Nussbaumer
1401 6e34b628 Guido Trotter
    self.beparams = UpgradeGroupedParams(self.beparams,
1402 6e34b628 Guido Trotter
                                         constants.BEC_DEFAULTS)
1403 8c72ab2b Guido Trotter
    for beparams_group in self.beparams:
1404 8c72ab2b Guido Trotter
      UpgradeBeParams(self.beparams[beparams_group])
1405 8c72ab2b Guido Trotter
1406 c8fcde47 Guido Trotter
    migrate_default_bridge = not self.nicparams
1407 c8fcde47 Guido Trotter
    self.nicparams = UpgradeGroupedParams(self.nicparams,
1408 c8fcde47 Guido Trotter
                                          constants.NICC_DEFAULTS)
1409 c8fcde47 Guido Trotter
    if migrate_default_bridge:
1410 c8fcde47 Guido Trotter
      self.nicparams[constants.PP_DEFAULT][constants.NIC_LINK] = \
1411 c8fcde47 Guido Trotter
        self.default_bridge
1412 c1b42c18 Guido Trotter
1413 b86a6bcd Guido Trotter
    if self.modify_etc_hosts is None:
1414 b86a6bcd Guido Trotter
      self.modify_etc_hosts = True
1415 b86a6bcd Guido Trotter
1416 b989b9d9 Ken Wehr
    if self.modify_ssh_setup is None:
1417 b989b9d9 Ken Wehr
      self.modify_ssh_setup = True
1418 b989b9d9 Ken Wehr
1419 73f1d185 Stephen Shirley
    # default_bridge is no longer used in 2.1. The slot is left there to
1420 90d118fd Guido Trotter
    # support auto-upgrading. It can be removed once we decide to deprecate
1421 90d118fd Guido Trotter
    # upgrading straight from 2.0.
1422 9b31ca85 Guido Trotter
    if self.default_bridge is not None:
1423 9b31ca85 Guido Trotter
      self.default_bridge = None
1424 9b31ca85 Guido Trotter
1425 90d118fd Guido Trotter
    # default_hypervisor is just the first enabled one in 2.1. This slot and
1426 90d118fd Guido Trotter
    # code can be removed once upgrading straight from 2.0 is deprecated.
1427 066f465d Guido Trotter
    if self.default_hypervisor is not None:
1428 016d04b3 Michael Hanselmann
      self.enabled_hypervisors = ([self.default_hypervisor] +
1429 066f465d Guido Trotter
        [hvname for hvname in self.enabled_hypervisors
1430 016d04b3 Michael Hanselmann
         if hvname != self.default_hypervisor])
1431 066f465d Guido Trotter
      self.default_hypervisor = None
1432 066f465d Guido Trotter
1433 3953242f Iustin Pop
    # maintain_node_health added after 2.1.1
1434 3953242f Iustin Pop
    if self.maintain_node_health is None:
1435 3953242f Iustin Pop
      self.maintain_node_health = False
1436 3953242f Iustin Pop
1437 4437d889 Balazs Lecz
    if self.uid_pool is None:
1438 4437d889 Balazs Lecz
      self.uid_pool = []
1439 4437d889 Balazs Lecz
1440 bf4af505 Apollon Oikonomopoulos
    if self.default_iallocator is None:
1441 bf4af505 Apollon Oikonomopoulos
      self.default_iallocator = ""
1442 bf4af505 Apollon Oikonomopoulos
1443 999b183c Iustin Pop
    # reserved_lvs added before 2.2
1444 999b183c Iustin Pop
    if self.reserved_lvs is None:
1445 999b183c Iustin Pop
      self.reserved_lvs = []
1446 999b183c Iustin Pop
1447 546b1111 Iustin Pop
    # hidden and blacklisted operating systems added before 2.2.1
1448 87b2cd45 Iustin Pop
    if self.hidden_os is None:
1449 87b2cd45 Iustin Pop
      self.hidden_os = []
1450 546b1111 Iustin Pop
1451 87b2cd45 Iustin Pop
    if self.blacklisted_os is None:
1452 87b2cd45 Iustin Pop
      self.blacklisted_os = []
1453 546b1111 Iustin Pop
1454 f4c9af7a Guido Trotter
    # primary_ip_family added before 2.3
1455 f4c9af7a Guido Trotter
    if self.primary_ip_family is None:
1456 f4c9af7a Guido Trotter
      self.primary_ip_family = AF_INET
1457 f4c9af7a Guido Trotter
1458 0007f3ab Andrea Spadaccini
    if self.master_netmask is None:
1459 0007f3ab Andrea Spadaccini
      ipcls = netutils.IPAddress.GetClassFromIpFamily(self.primary_ip_family)
1460 0007f3ab Andrea Spadaccini
      self.master_netmask = ipcls.iplen
1461 0007f3ab Andrea Spadaccini
1462 3d914585 Renรฉ Nussbaumer
    if self.prealloc_wipe_disks is None:
1463 3d914585 Renรฉ Nussbaumer
      self.prealloc_wipe_disks = False
1464 3d914585 Renรฉ Nussbaumer
1465 e8f472d1 Iustin Pop
    # shared_file_storage_dir added before 2.5
1466 e8f472d1 Iustin Pop
    if self.shared_file_storage_dir is None:
1467 e8f472d1 Iustin Pop
      self.shared_file_storage_dir = ""
1468 e8f472d1 Iustin Pop
1469 33be7576 Andrea Spadaccini
    if self.use_external_mip_script is None:
1470 33be7576 Andrea Spadaccini
      self.use_external_mip_script = False
1471 33be7576 Andrea Spadaccini
1472 bc5d0215 Andrea Spadaccini
    self.diskparams = UpgradeDiskParams(self.diskparams)
1473 bc5d0215 Andrea Spadaccini
1474 918eb80b Agata Murawska
    # instance policy added before 2.6
1475 918eb80b Agata Murawska
    if self.ipolicy is None:
1476 918eb80b Agata Murawska
      self.ipolicy = MakeEmptyIPolicy()
1477 918eb80b Agata Murawska
1478 0fbedb7a Michael Hanselmann
  @property
1479 0fbedb7a Michael Hanselmann
  def primary_hypervisor(self):
1480 0fbedb7a Michael Hanselmann
    """The first hypervisor is the primary.
1481 0fbedb7a Michael Hanselmann

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

1484 0fbedb7a Michael Hanselmann
    """
1485 0fbedb7a Michael Hanselmann
    return self.enabled_hypervisors[0]
1486 0fbedb7a Michael Hanselmann
1487 319856a9 Michael Hanselmann
  def ToDict(self):
1488 319856a9 Michael Hanselmann
    """Custom function for cluster.
1489 319856a9 Michael Hanselmann

1490 319856a9 Michael Hanselmann
    """
1491 b60ae2ca Iustin Pop
    mydict = super(Cluster, self).ToDict()
1492 319856a9 Michael Hanselmann
    mydict["tcpudp_port_pool"] = list(self.tcpudp_port_pool)
1493 319856a9 Michael Hanselmann
    return mydict
1494 319856a9 Michael Hanselmann
1495 319856a9 Michael Hanselmann
  @classmethod
1496 319856a9 Michael Hanselmann
  def FromDict(cls, val):
1497 319856a9 Michael Hanselmann
    """Custom function for cluster.
1498 319856a9 Michael Hanselmann

1499 319856a9 Michael Hanselmann
    """
1500 b60ae2ca Iustin Pop
    obj = super(Cluster, cls).FromDict(val)
1501 319856a9 Michael Hanselmann
    if not isinstance(obj.tcpudp_port_pool, set):
1502 319856a9 Michael Hanselmann
      obj.tcpudp_port_pool = set(obj.tcpudp_port_pool)
1503 319856a9 Michael Hanselmann
    return obj
1504 319856a9 Michael Hanselmann
1505 d63479b5 Iustin Pop
  def GetHVDefaults(self, hypervisor, os_name=None, skip_keys=None):
1506 d63479b5 Iustin Pop
    """Get the default hypervisor parameters for the cluster.
1507 d63479b5 Iustin Pop

1508 d63479b5 Iustin Pop
    @param hypervisor: the hypervisor name
1509 d63479b5 Iustin Pop
    @param os_name: if specified, we'll also update the defaults for this OS
1510 d63479b5 Iustin Pop
    @param skip_keys: if passed, list of keys not to use
1511 d63479b5 Iustin Pop
    @return: the defaults dict
1512 d63479b5 Iustin Pop

1513 d63479b5 Iustin Pop
    """
1514 d63479b5 Iustin Pop
    if skip_keys is None:
1515 d63479b5 Iustin Pop
      skip_keys = []
1516 d63479b5 Iustin Pop
1517 d63479b5 Iustin Pop
    fill_stack = [self.hvparams.get(hypervisor, {})]
1518 d63479b5 Iustin Pop
    if os_name is not None:
1519 d63479b5 Iustin Pop
      os_hvp = self.os_hvp.get(os_name, {}).get(hypervisor, {})
1520 d63479b5 Iustin Pop
      fill_stack.append(os_hvp)
1521 d63479b5 Iustin Pop
1522 d63479b5 Iustin Pop
    ret_dict = {}
1523 d63479b5 Iustin Pop
    for o_dict in fill_stack:
1524 d63479b5 Iustin Pop
      ret_dict = FillDict(ret_dict, o_dict, skip_keys=skip_keys)
1525 d63479b5 Iustin Pop
1526 d63479b5 Iustin Pop
    return ret_dict
1527 d63479b5 Iustin Pop
1528 73e0328b Iustin Pop
  def SimpleFillHV(self, hv_name, os_name, hvparams, skip_globals=False):
1529 73e0328b Iustin Pop
    """Fill a given hvparams dict with cluster defaults.
1530 73e0328b Iustin Pop

1531 73e0328b Iustin Pop
    @type hv_name: string
1532 73e0328b Iustin Pop
    @param hv_name: the hypervisor to use
1533 73e0328b Iustin Pop
    @type os_name: string
1534 73e0328b Iustin Pop
    @param os_name: the OS to use for overriding the hypervisor defaults
1535 73e0328b Iustin Pop
    @type skip_globals: boolean
1536 73e0328b Iustin Pop
    @param skip_globals: if True, the global hypervisor parameters will
1537 73e0328b Iustin Pop
        not be filled
1538 73e0328b Iustin Pop
    @rtype: dict
1539 73e0328b Iustin Pop
    @return: a copy of the given hvparams with missing keys filled from
1540 73e0328b Iustin Pop
        the cluster defaults
1541 73e0328b Iustin Pop

1542 73e0328b Iustin Pop
    """
1543 73e0328b Iustin Pop
    if skip_globals:
1544 73e0328b Iustin Pop
      skip_keys = constants.HVC_GLOBALS
1545 73e0328b Iustin Pop
    else:
1546 73e0328b Iustin Pop
      skip_keys = []
1547 73e0328b Iustin Pop
1548 73e0328b Iustin Pop
    def_dict = self.GetHVDefaults(hv_name, os_name, skip_keys=skip_keys)
1549 73e0328b Iustin Pop
    return FillDict(def_dict, hvparams, skip_keys=skip_keys)
1550 d63479b5 Iustin Pop
1551 7736a5f2 Iustin Pop
  def FillHV(self, instance, skip_globals=False):
1552 73e0328b Iustin Pop
    """Fill an instance's hvparams dict with cluster defaults.
1553 5bf7b5cf Iustin Pop

1554 a2a24f4c Guido Trotter
    @type instance: L{objects.Instance}
1555 5bf7b5cf Iustin Pop
    @param instance: the instance parameter to fill
1556 7736a5f2 Iustin Pop
    @type skip_globals: boolean
1557 7736a5f2 Iustin Pop
    @param skip_globals: if True, the global hypervisor parameters will
1558 7736a5f2 Iustin Pop
        not be filled
1559 5bf7b5cf Iustin Pop
    @rtype: dict
1560 5bf7b5cf Iustin Pop
    @return: a copy of the instance's hvparams with missing keys filled from
1561 5bf7b5cf Iustin Pop
        the cluster defaults
1562 5bf7b5cf Iustin Pop

1563 5bf7b5cf Iustin Pop
    """
1564 73e0328b Iustin Pop
    return self.SimpleFillHV(instance.hypervisor, instance.os,
1565 73e0328b Iustin Pop
                             instance.hvparams, skip_globals)
1566 17463d22 Renรฉ Nussbaumer
1567 73e0328b Iustin Pop
  def SimpleFillBE(self, beparams):
1568 73e0328b Iustin Pop
    """Fill a given beparams dict with cluster defaults.
1569 73e0328b Iustin Pop

1570 06596a60 Guido Trotter
    @type beparams: dict
1571 06596a60 Guido Trotter
    @param beparams: the dict to fill
1572 73e0328b Iustin Pop
    @rtype: dict
1573 73e0328b Iustin Pop
    @return: a copy of the passed in beparams with missing keys filled
1574 73e0328b Iustin Pop
        from the cluster defaults
1575 73e0328b Iustin Pop

1576 73e0328b Iustin Pop
    """
1577 73e0328b Iustin Pop
    return FillDict(self.beparams.get(constants.PP_DEFAULT, {}), beparams)
1578 5bf7b5cf Iustin Pop
1579 5bf7b5cf Iustin Pop
  def FillBE(self, instance):
1580 73e0328b Iustin Pop
    """Fill an instance's beparams dict with cluster defaults.
1581 5bf7b5cf Iustin Pop

1582 a2a24f4c Guido Trotter
    @type instance: L{objects.Instance}
1583 5bf7b5cf Iustin Pop
    @param instance: the instance parameter to fill
1584 5bf7b5cf Iustin Pop
    @rtype: dict
1585 5bf7b5cf Iustin Pop
    @return: a copy of the instance's beparams with missing keys filled from
1586 5bf7b5cf Iustin Pop
        the cluster defaults
1587 5bf7b5cf Iustin Pop

1588 5bf7b5cf Iustin Pop
    """
1589 73e0328b Iustin Pop
    return self.SimpleFillBE(instance.beparams)
1590 73e0328b Iustin Pop
1591 73e0328b Iustin Pop
  def SimpleFillNIC(self, nicparams):
1592 73e0328b Iustin Pop
    """Fill a given nicparams dict with cluster defaults.
1593 73e0328b Iustin Pop

1594 06596a60 Guido Trotter
    @type nicparams: dict
1595 06596a60 Guido Trotter
    @param nicparams: the dict to fill
1596 73e0328b Iustin Pop
    @rtype: dict
1597 73e0328b Iustin Pop
    @return: a copy of the passed in nicparams with missing keys filled
1598 73e0328b Iustin Pop
        from the cluster defaults
1599 73e0328b Iustin Pop

1600 73e0328b Iustin Pop
    """
1601 73e0328b Iustin Pop
    return FillDict(self.nicparams.get(constants.PP_DEFAULT, {}), nicparams)
1602 5bf7b5cf Iustin Pop
1603 1bdcbbab Iustin Pop
  def SimpleFillOS(self, os_name, os_params):
1604 1bdcbbab Iustin Pop
    """Fill an instance's osparams dict with cluster defaults.
1605 1bdcbbab Iustin Pop

1606 1bdcbbab Iustin Pop
    @type os_name: string
1607 1bdcbbab Iustin Pop
    @param os_name: the OS name to use
1608 1bdcbbab Iustin Pop
    @type os_params: dict
1609 1bdcbbab Iustin Pop
    @param os_params: the dict to fill with default values
1610 1bdcbbab Iustin Pop
    @rtype: dict
1611 1bdcbbab Iustin Pop
    @return: a copy of the instance's osparams with missing keys filled from
1612 1bdcbbab Iustin Pop
        the cluster defaults
1613 1bdcbbab Iustin Pop

1614 1bdcbbab Iustin Pop
    """
1615 1bdcbbab Iustin Pop
    name_only = os_name.split("+", 1)[0]
1616 1bdcbbab Iustin Pop
    # base OS
1617 1bdcbbab Iustin Pop
    result = self.osparams.get(name_only, {})
1618 1bdcbbab Iustin Pop
    # OS with variant
1619 1bdcbbab Iustin Pop
    result = FillDict(result, self.osparams.get(os_name, {}))
1620 1bdcbbab Iustin Pop
    # specified params
1621 1bdcbbab Iustin Pop
    return FillDict(result, os_params)
1622 1bdcbbab Iustin Pop
1623 2da9f556 Renรฉ Nussbaumer
  @staticmethod
1624 2da9f556 Renรฉ Nussbaumer
  def SimpleFillHvState(hv_state):
1625 2da9f556 Renรฉ Nussbaumer
    """Fill an hv_state sub dict with cluster defaults.
1626 2da9f556 Renรฉ Nussbaumer

1627 2da9f556 Renรฉ Nussbaumer
    """
1628 2da9f556 Renรฉ Nussbaumer
    return FillDict(constants.HVST_DEFAULTS, hv_state)
1629 2da9f556 Renรฉ Nussbaumer
1630 2da9f556 Renรฉ Nussbaumer
  @staticmethod
1631 2da9f556 Renรฉ Nussbaumer
  def SimpleFillDiskState(disk_state):
1632 2da9f556 Renรฉ Nussbaumer
    """Fill an disk_state sub dict with cluster defaults.
1633 2da9f556 Renรฉ Nussbaumer

1634 2da9f556 Renรฉ Nussbaumer
    """
1635 2da9f556 Renรฉ Nussbaumer
    return FillDict(constants.DS_DEFAULTS, disk_state)
1636 2da9f556 Renรฉ Nussbaumer
1637 095e71aa Renรฉ Nussbaumer
  def FillND(self, node, nodegroup):
1638 ce523de1 Michael Hanselmann
    """Return filled out ndparams for L{objects.NodeGroup} and L{objects.Node}
1639 095e71aa Renรฉ Nussbaumer

1640 095e71aa Renรฉ Nussbaumer
    @type node: L{objects.Node}
1641 095e71aa Renรฉ Nussbaumer
    @param node: A Node object to fill
1642 095e71aa Renรฉ Nussbaumer
    @type nodegroup: L{objects.NodeGroup}
1643 095e71aa Renรฉ Nussbaumer
    @param nodegroup: A Node object to fill
1644 095e71aa Renรฉ Nussbaumer
    @return a copy of the node's ndparams with defaults filled
1645 095e71aa Renรฉ Nussbaumer

1646 095e71aa Renรฉ Nussbaumer
    """
1647 095e71aa Renรฉ Nussbaumer
    return self.SimpleFillND(nodegroup.FillND(node))
1648 095e71aa Renรฉ Nussbaumer
1649 095e71aa Renรฉ Nussbaumer
  def SimpleFillND(self, ndparams):
1650 095e71aa Renรฉ Nussbaumer
    """Fill a given ndparams dict with defaults.
1651 095e71aa Renรฉ Nussbaumer

1652 095e71aa Renรฉ Nussbaumer
    @type ndparams: dict
1653 095e71aa Renรฉ Nussbaumer
    @param ndparams: the dict to fill
1654 095e71aa Renรฉ Nussbaumer
    @rtype: dict
1655 095e71aa Renรฉ Nussbaumer
    @return: a copy of the passed in ndparams with missing keys filled
1656 095e71aa Renรฉ Nussbaumer
        from the cluster defaults
1657 095e71aa Renรฉ Nussbaumer

1658 095e71aa Renรฉ Nussbaumer
    """
1659 095e71aa Renรฉ Nussbaumer
    return FillDict(self.ndparams, ndparams)
1660 095e71aa Renรฉ Nussbaumer
1661 918eb80b Agata Murawska
  def SimpleFillIPolicy(self, ipolicy):
1662 918eb80b Agata Murawska
    """ Fill instance policy dict with defaults.
1663 918eb80b Agata Murawska

1664 918eb80b Agata Murawska
    @type ipolicy: dict
1665 918eb80b Agata Murawska
    @param ipolicy: the dict to fill
1666 918eb80b Agata Murawska
    @rtype: dict
1667 918eb80b Agata Murawska
    @return: a copy of passed ipolicy with missing keys filled from
1668 918eb80b Agata Murawska
      the cluster defaults
1669 918eb80b Agata Murawska

1670 918eb80b Agata Murawska
    """
1671 918eb80b Agata Murawska
    return FillDictOfDicts(self.ipolicy, ipolicy)
1672 918eb80b Agata Murawska
1673 5c947f38 Iustin Pop
1674 96acbc09 Michael Hanselmann
class BlockDevStatus(ConfigObject):
1675 96acbc09 Michael Hanselmann
  """Config object representing the status of a block device."""
1676 96acbc09 Michael Hanselmann
  __slots__ = [
1677 96acbc09 Michael Hanselmann
    "dev_path",
1678 96acbc09 Michael Hanselmann
    "major",
1679 96acbc09 Michael Hanselmann
    "minor",
1680 96acbc09 Michael Hanselmann
    "sync_percent",
1681 96acbc09 Michael Hanselmann
    "estimated_time",
1682 96acbc09 Michael Hanselmann
    "is_degraded",
1683 f208978a Michael Hanselmann
    "ldisk_status",
1684 96acbc09 Michael Hanselmann
    ]
1685 96acbc09 Michael Hanselmann
1686 96acbc09 Michael Hanselmann
1687 2d76b580 Michael Hanselmann
class ImportExportStatus(ConfigObject):
1688 2d76b580 Michael Hanselmann
  """Config object representing the status of an import or export."""
1689 2d76b580 Michael Hanselmann
  __slots__ = [
1690 2d76b580 Michael Hanselmann
    "recent_output",
1691 2d76b580 Michael Hanselmann
    "listen_port",
1692 2d76b580 Michael Hanselmann
    "connected",
1693 c08d76f5 Michael Hanselmann
    "progress_mbytes",
1694 c08d76f5 Michael Hanselmann
    "progress_throughput",
1695 c08d76f5 Michael Hanselmann
    "progress_eta",
1696 c08d76f5 Michael Hanselmann
    "progress_percent",
1697 2d76b580 Michael Hanselmann
    "exit_status",
1698 2d76b580 Michael Hanselmann
    "error_message",
1699 2d76b580 Michael Hanselmann
    ] + _TIMESTAMPS
1700 2d76b580 Michael Hanselmann
1701 2d76b580 Michael Hanselmann
1702 eb630f50 Michael Hanselmann
class ImportExportOptions(ConfigObject):
1703 eb630f50 Michael Hanselmann
  """Options for import/export daemon
1704 eb630f50 Michael Hanselmann

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

1712 eb630f50 Michael Hanselmann
  """
1713 eb630f50 Michael Hanselmann
  __slots__ = [
1714 eb630f50 Michael Hanselmann
    "key_name",
1715 eb630f50 Michael Hanselmann
    "ca_pem",
1716 a5310c2a Michael Hanselmann
    "compress",
1717 af1d39b1 Michael Hanselmann
    "magic",
1718 855d2fc7 Michael Hanselmann
    "ipv6",
1719 4478301b Michael Hanselmann
    "connect_timeout",
1720 eb630f50 Michael Hanselmann
    ]
1721 eb630f50 Michael Hanselmann
1722 eb630f50 Michael Hanselmann
1723 18d750b9 Guido Trotter
class ConfdRequest(ConfigObject):
1724 18d750b9 Guido Trotter
  """Object holding a confd request.
1725 18d750b9 Guido Trotter

1726 18d750b9 Guido Trotter
  @ivar protocol: confd protocol version
1727 18d750b9 Guido Trotter
  @ivar type: confd query type
1728 18d750b9 Guido Trotter
  @ivar query: query request
1729 18d750b9 Guido Trotter
  @ivar rsalt: requested reply salt
1730 18d750b9 Guido Trotter

1731 18d750b9 Guido Trotter
  """
1732 18d750b9 Guido Trotter
  __slots__ = [
1733 18d750b9 Guido Trotter
    "protocol",
1734 18d750b9 Guido Trotter
    "type",
1735 18d750b9 Guido Trotter
    "query",
1736 18d750b9 Guido Trotter
    "rsalt",
1737 18d750b9 Guido Trotter
    ]
1738 18d750b9 Guido Trotter
1739 18d750b9 Guido Trotter
1740 18d750b9 Guido Trotter
class ConfdReply(ConfigObject):
1741 18d750b9 Guido Trotter
  """Object holding a confd reply.
1742 18d750b9 Guido Trotter

1743 18d750b9 Guido Trotter
  @ivar protocol: confd protocol version
1744 18d750b9 Guido Trotter
  @ivar status: reply status code (ok, error)
1745 18d750b9 Guido Trotter
  @ivar answer: confd query reply
1746 18d750b9 Guido Trotter
  @ivar serial: configuration serial number
1747 18d750b9 Guido Trotter

1748 18d750b9 Guido Trotter
  """
1749 18d750b9 Guido Trotter
  __slots__ = [
1750 18d750b9 Guido Trotter
    "protocol",
1751 18d750b9 Guido Trotter
    "status",
1752 18d750b9 Guido Trotter
    "answer",
1753 18d750b9 Guido Trotter
    "serial",
1754 18d750b9 Guido Trotter
    ]
1755 18d750b9 Guido Trotter
1756 18d750b9 Guido Trotter
1757 707f23b5 Michael Hanselmann
class QueryFieldDefinition(ConfigObject):
1758 707f23b5 Michael Hanselmann
  """Object holding a query field definition.
1759 707f23b5 Michael Hanselmann

1760 24d6d3e2 Michael Hanselmann
  @ivar name: Field name
1761 707f23b5 Michael Hanselmann
  @ivar title: Human-readable title
1762 707f23b5 Michael Hanselmann
  @ivar kind: Field type
1763 1ae17369 Michael Hanselmann
  @ivar doc: Human-readable description
1764 707f23b5 Michael Hanselmann

1765 707f23b5 Michael Hanselmann
  """
1766 707f23b5 Michael Hanselmann
  __slots__ = [
1767 707f23b5 Michael Hanselmann
    "name",
1768 707f23b5 Michael Hanselmann
    "title",
1769 707f23b5 Michael Hanselmann
    "kind",
1770 1ae17369 Michael Hanselmann
    "doc",
1771 707f23b5 Michael Hanselmann
    ]
1772 707f23b5 Michael Hanselmann
1773 707f23b5 Michael Hanselmann
1774 0538c375 Michael Hanselmann
class _QueryResponseBase(ConfigObject):
1775 0538c375 Michael Hanselmann
  __slots__ = [
1776 0538c375 Michael Hanselmann
    "fields",
1777 0538c375 Michael Hanselmann
    ]
1778 0538c375 Michael Hanselmann
1779 0538c375 Michael Hanselmann
  def ToDict(self):
1780 0538c375 Michael Hanselmann
    """Custom function for serializing.
1781 0538c375 Michael Hanselmann

1782 0538c375 Michael Hanselmann
    """
1783 0538c375 Michael Hanselmann
    mydict = super(_QueryResponseBase, self).ToDict()
1784 0538c375 Michael Hanselmann
    mydict["fields"] = self._ContainerToDicts(mydict["fields"])
1785 0538c375 Michael Hanselmann
    return mydict
1786 0538c375 Michael Hanselmann
1787 0538c375 Michael Hanselmann
  @classmethod
1788 0538c375 Michael Hanselmann
  def FromDict(cls, val):
1789 0538c375 Michael Hanselmann
    """Custom function for de-serializing.
1790 0538c375 Michael Hanselmann

1791 0538c375 Michael Hanselmann
    """
1792 0538c375 Michael Hanselmann
    obj = super(_QueryResponseBase, cls).FromDict(val)
1793 0538c375 Michael Hanselmann
    obj.fields = cls._ContainerFromDicts(obj.fields, list, QueryFieldDefinition)
1794 0538c375 Michael Hanselmann
    return obj
1795 0538c375 Michael Hanselmann
1796 0538c375 Michael Hanselmann
1797 24d6d3e2 Michael Hanselmann
class QueryRequest(ConfigObject):
1798 24d6d3e2 Michael Hanselmann
  """Object holding a query request.
1799 24d6d3e2 Michael Hanselmann

1800 24d6d3e2 Michael Hanselmann
  """
1801 24d6d3e2 Michael Hanselmann
  __slots__ = [
1802 24d6d3e2 Michael Hanselmann
    "what",
1803 24d6d3e2 Michael Hanselmann
    "fields",
1804 2e5c33db Iustin Pop
    "qfilter",
1805 24d6d3e2 Michael Hanselmann
    ]
1806 24d6d3e2 Michael Hanselmann
1807 24d6d3e2 Michael Hanselmann
1808 0538c375 Michael Hanselmann
class QueryResponse(_QueryResponseBase):
1809 24d6d3e2 Michael Hanselmann
  """Object holding the response to a query.
1810 24d6d3e2 Michael Hanselmann

1811 24d6d3e2 Michael Hanselmann
  @ivar fields: List of L{QueryFieldDefinition} objects
1812 24d6d3e2 Michael Hanselmann
  @ivar data: Requested data
1813 24d6d3e2 Michael Hanselmann

1814 24d6d3e2 Michael Hanselmann
  """
1815 24d6d3e2 Michael Hanselmann
  __slots__ = [
1816 24d6d3e2 Michael Hanselmann
    "data",
1817 24d6d3e2 Michael Hanselmann
    ]
1818 24d6d3e2 Michael Hanselmann
1819 24d6d3e2 Michael Hanselmann
1820 24d6d3e2 Michael Hanselmann
class QueryFieldsRequest(ConfigObject):
1821 24d6d3e2 Michael Hanselmann
  """Object holding a request for querying available fields.
1822 24d6d3e2 Michael Hanselmann

1823 24d6d3e2 Michael Hanselmann
  """
1824 24d6d3e2 Michael Hanselmann
  __slots__ = [
1825 24d6d3e2 Michael Hanselmann
    "what",
1826 24d6d3e2 Michael Hanselmann
    "fields",
1827 24d6d3e2 Michael Hanselmann
    ]
1828 24d6d3e2 Michael Hanselmann
1829 24d6d3e2 Michael Hanselmann
1830 0538c375 Michael Hanselmann
class QueryFieldsResponse(_QueryResponseBase):
1831 24d6d3e2 Michael Hanselmann
  """Object holding the response to a query for fields.
1832 24d6d3e2 Michael Hanselmann

1833 24d6d3e2 Michael Hanselmann
  @ivar fields: List of L{QueryFieldDefinition} objects
1834 24d6d3e2 Michael Hanselmann

1835 24d6d3e2 Michael Hanselmann
  """
1836 24d6d3e2 Michael Hanselmann
  __slots__ = [
1837 24d6d3e2 Michael Hanselmann
    ]
1838 24d6d3e2 Michael Hanselmann
1839 24d6d3e2 Michael Hanselmann
1840 6a1434d7 Andrea Spadaccini
class MigrationStatus(ConfigObject):
1841 6a1434d7 Andrea Spadaccini
  """Object holding the status of a migration.
1842 6a1434d7 Andrea Spadaccini

1843 6a1434d7 Andrea Spadaccini
  """
1844 6a1434d7 Andrea Spadaccini
  __slots__ = [
1845 6a1434d7 Andrea Spadaccini
    "status",
1846 6a1434d7 Andrea Spadaccini
    "transferred_ram",
1847 6a1434d7 Andrea Spadaccini
    "total_ram",
1848 6a1434d7 Andrea Spadaccini
    ]
1849 6a1434d7 Andrea Spadaccini
1850 6a1434d7 Andrea Spadaccini
1851 25ce3ec4 Michael Hanselmann
class InstanceConsole(ConfigObject):
1852 25ce3ec4 Michael Hanselmann
  """Object describing how to access the console of an instance.
1853 25ce3ec4 Michael Hanselmann

1854 25ce3ec4 Michael Hanselmann
  """
1855 25ce3ec4 Michael Hanselmann
  __slots__ = [
1856 25ce3ec4 Michael Hanselmann
    "instance",
1857 25ce3ec4 Michael Hanselmann
    "kind",
1858 25ce3ec4 Michael Hanselmann
    "message",
1859 25ce3ec4 Michael Hanselmann
    "host",
1860 25ce3ec4 Michael Hanselmann
    "port",
1861 25ce3ec4 Michael Hanselmann
    "user",
1862 25ce3ec4 Michael Hanselmann
    "command",
1863 25ce3ec4 Michael Hanselmann
    "display",
1864 25ce3ec4 Michael Hanselmann
    ]
1865 25ce3ec4 Michael Hanselmann
1866 25ce3ec4 Michael Hanselmann
  def Validate(self):
1867 25ce3ec4 Michael Hanselmann
    """Validates contents of this object.
1868 25ce3ec4 Michael Hanselmann

1869 25ce3ec4 Michael Hanselmann
    """
1870 25ce3ec4 Michael Hanselmann
    assert self.kind in constants.CONS_ALL, "Unknown console type"
1871 25ce3ec4 Michael Hanselmann
    assert self.instance, "Missing instance name"
1872 4d2cdb5a Andrea Spadaccini
    assert self.message or self.kind in [constants.CONS_SSH,
1873 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1874 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_VNC]
1875 25ce3ec4 Michael Hanselmann
    assert self.host or self.kind == constants.CONS_MESSAGE
1876 25ce3ec4 Michael Hanselmann
    assert self.port or self.kind in [constants.CONS_MESSAGE,
1877 25ce3ec4 Michael Hanselmann
                                      constants.CONS_SSH]
1878 25ce3ec4 Michael Hanselmann
    assert self.user or self.kind in [constants.CONS_MESSAGE,
1879 4d2cdb5a Andrea Spadaccini
                                      constants.CONS_SPICE,
1880 25ce3ec4 Michael Hanselmann
                                      constants.CONS_VNC]
1881 25ce3ec4 Michael Hanselmann
    assert self.command or self.kind in [constants.CONS_MESSAGE,
1882 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1883 25ce3ec4 Michael Hanselmann
                                         constants.CONS_VNC]
1884 25ce3ec4 Michael Hanselmann
    assert self.display or self.kind in [constants.CONS_MESSAGE,
1885 4d2cdb5a Andrea Spadaccini
                                         constants.CONS_SPICE,
1886 25ce3ec4 Michael Hanselmann
                                         constants.CONS_SSH]
1887 25ce3ec4 Michael Hanselmann
    return True
1888 25ce3ec4 Michael Hanselmann
1889 25ce3ec4 Michael Hanselmann
1890 a8083063 Iustin Pop
class SerializableConfigParser(ConfigParser.SafeConfigParser):
1891 a8083063 Iustin Pop
  """Simple wrapper over ConfigParse that allows serialization.
1892 a8083063 Iustin Pop

1893 a8083063 Iustin Pop
  This class is basically ConfigParser.SafeConfigParser with two
1894 a8083063 Iustin Pop
  additional methods that allow it to serialize/unserialize to/from a
1895 a8083063 Iustin Pop
  buffer.
1896 a8083063 Iustin Pop

1897 a8083063 Iustin Pop
  """
1898 a8083063 Iustin Pop
  def Dumps(self):
1899 a8083063 Iustin Pop
    """Dump this instance and return the string representation."""
1900 a8083063 Iustin Pop
    buf = StringIO()
1901 a8083063 Iustin Pop
    self.write(buf)
1902 a8083063 Iustin Pop
    return buf.getvalue()
1903 a8083063 Iustin Pop
1904 b39bf4bb Guido Trotter
  @classmethod
1905 b39bf4bb Guido Trotter
  def Loads(cls, data):
1906 a8083063 Iustin Pop
    """Load data from a string."""
1907 a8083063 Iustin Pop
    buf = StringIO(data)
1908 b39bf4bb Guido Trotter
    cfp = cls()
1909 a8083063 Iustin Pop
    cfp.readfp(buf)
1910 a8083063 Iustin Pop
    return cfp