Statistics
| Branch: | Tag: | Revision:

root / lib / objects.py @ 2057f6c7

History | View | Annotate | Download (12.4 kB)

1 a8083063 Iustin Pop
#!/usr/bin/python
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 a8083063 Iustin Pop
# Copyright (C) 2006, 2007 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 a8083063 Iustin Pop
30 a8083063 Iustin Pop
import cPickle
31 a8083063 Iustin Pop
from cStringIO import StringIO
32 a8083063 Iustin Pop
import ConfigParser
33 5c947f38 Iustin Pop
import re
34 a8083063 Iustin Pop
35 a8083063 Iustin Pop
from ganeti import errors
36 5c947f38 Iustin Pop
from ganeti import constants
37 a8083063 Iustin Pop
38 a8083063 Iustin Pop
39 a8083063 Iustin Pop
__all__ = ["ConfigObject", "ConfigData", "NIC", "Disk", "Instance",
40 a8083063 Iustin Pop
           "OS", "Node", "Cluster"]
41 a8083063 Iustin Pop
42 a8083063 Iustin Pop
43 a8083063 Iustin Pop
class ConfigObject(object):
44 a8083063 Iustin Pop
  """A generic config object.
45 a8083063 Iustin Pop

46 a8083063 Iustin Pop
  It has the following properties:
47 a8083063 Iustin Pop

48 a8083063 Iustin Pop
    - provides somewhat safe recursive unpickling and pickling for its classes
49 a8083063 Iustin Pop
    - unset attributes which are defined in slots are always returned
50 a8083063 Iustin Pop
      as None instead of raising an error
51 a8083063 Iustin Pop

52 a8083063 Iustin Pop
  Classes derived from this must always declare __slots__ (we use many
53 a8083063 Iustin Pop
  config objects and the memory reduction is useful.
54 a8083063 Iustin Pop

55 a8083063 Iustin Pop
  """
56 a8083063 Iustin Pop
  __slots__ = []
57 a8083063 Iustin Pop
58 a8083063 Iustin Pop
  def __init__(self, **kwargs):
59 a8083063 Iustin Pop
    for i in kwargs:
60 a8083063 Iustin Pop
      setattr(self, i, kwargs[i])
61 a8083063 Iustin Pop
62 a8083063 Iustin Pop
  def __getattr__(self, name):
63 a8083063 Iustin Pop
    if name not in self.__slots__:
64 3ecf6786 Iustin Pop
      raise AttributeError("Invalid object attribute %s.%s" %
65 3ecf6786 Iustin Pop
                           (type(self).__name__, name))
66 a8083063 Iustin Pop
    return None
67 a8083063 Iustin Pop
68 47c28c5b Michael Hanselmann
  def __setitem__(self, key, value):
69 47c28c5b Michael Hanselmann
    if key not in self.__slots__:
70 3ecf6786 Iustin Pop
      raise KeyError(key)
71 47c28c5b Michael Hanselmann
    setattr(self, key, value)
72 47c28c5b Michael Hanselmann
73 a8083063 Iustin Pop
  def __getstate__(self):
74 a8083063 Iustin Pop
    state = {}
75 a8083063 Iustin Pop
    for name in self.__slots__:
76 a8083063 Iustin Pop
      if hasattr(self, name):
77 a8083063 Iustin Pop
        state[name] = getattr(self, name)
78 a8083063 Iustin Pop
    return state
79 a8083063 Iustin Pop
80 a8083063 Iustin Pop
  def __setstate__(self, state):
81 a8083063 Iustin Pop
    for name in state:
82 a8083063 Iustin Pop
      if name in self.__slots__:
83 a8083063 Iustin Pop
        setattr(self, name, state[name])
84 a8083063 Iustin Pop
85 a8083063 Iustin Pop
  @staticmethod
86 a8083063 Iustin Pop
  def FindGlobal(module, name):
87 a8083063 Iustin Pop
    """Function filtering the allowed classes to be un-pickled.
88 a8083063 Iustin Pop

89 a8083063 Iustin Pop
    Currently, we only allow the classes from this module which are
90 a8083063 Iustin Pop
    derived from ConfigObject.
91 a8083063 Iustin Pop

92 a8083063 Iustin Pop
    """
93 a8083063 Iustin Pop
    # Also support the old module name (ganeti.config)
94 a8083063 Iustin Pop
    cls = None
95 a8083063 Iustin Pop
    if module == "ganeti.config" or module == "ganeti.objects":
96 a8083063 Iustin Pop
      if name == "ConfigData":
97 a8083063 Iustin Pop
        cls = ConfigData
98 a8083063 Iustin Pop
      elif name == "NIC":
99 a8083063 Iustin Pop
        cls = NIC
100 a8083063 Iustin Pop
      elif name == "Disk" or name == "BlockDev":
101 a8083063 Iustin Pop
        cls = Disk
102 a8083063 Iustin Pop
      elif name == "Instance":
103 a8083063 Iustin Pop
        cls = Instance
104 a8083063 Iustin Pop
      elif name == "OS":
105 a8083063 Iustin Pop
        cls = OS
106 a8083063 Iustin Pop
      elif name == "Node":
107 a8083063 Iustin Pop
        cls = Node
108 a8083063 Iustin Pop
      elif name == "Cluster":
109 a8083063 Iustin Pop
        cls = Cluster
110 264bb3c5 Michael Hanselmann
    elif module == "__builtin__":
111 264bb3c5 Michael Hanselmann
      if name == "set":
112 264bb3c5 Michael Hanselmann
        cls = set
113 a8083063 Iustin Pop
    if cls is None:
114 3ecf6786 Iustin Pop
      raise cPickle.UnpicklingError("Class %s.%s not allowed due to"
115 3ecf6786 Iustin Pop
                                    " security concerns" % (module, name))
116 a8083063 Iustin Pop
    return cls
117 a8083063 Iustin Pop
118 a8083063 Iustin Pop
  def Dump(self, fobj):
119 a8083063 Iustin Pop
    """Dump this instance to a file object.
120 a8083063 Iustin Pop

121 a8083063 Iustin Pop
    Note that we use the HIGHEST_PROTOCOL, as it brings benefits for
122 a8083063 Iustin Pop
    the new classes.
123 a8083063 Iustin Pop

124 a8083063 Iustin Pop
    """
125 a8083063 Iustin Pop
    dumper = cPickle.Pickler(fobj, cPickle.HIGHEST_PROTOCOL)
126 a8083063 Iustin Pop
    dumper.dump(self)
127 a8083063 Iustin Pop
128 a8083063 Iustin Pop
  @staticmethod
129 a8083063 Iustin Pop
  def Load(fobj):
130 a8083063 Iustin Pop
    """Unpickle data from the given stream.
131 a8083063 Iustin Pop

132 a8083063 Iustin Pop
    This uses the `FindGlobal` function to filter the allowed classes.
133 a8083063 Iustin Pop

134 a8083063 Iustin Pop
    """
135 a8083063 Iustin Pop
    loader = cPickle.Unpickler(fobj)
136 a8083063 Iustin Pop
    loader.find_global = ConfigObject.FindGlobal
137 a8083063 Iustin Pop
    return loader.load()
138 a8083063 Iustin Pop
139 a8083063 Iustin Pop
  def Dumps(self):
140 a8083063 Iustin Pop
    """Dump this instance and return the string representation."""
141 a8083063 Iustin Pop
    buf = StringIO()
142 a8083063 Iustin Pop
    self.Dump(buf)
143 a8083063 Iustin Pop
    return buf.getvalue()
144 a8083063 Iustin Pop
145 a8083063 Iustin Pop
  @staticmethod
146 a8083063 Iustin Pop
  def Loads(data):
147 a8083063 Iustin Pop
    """Load data from a string."""
148 a8083063 Iustin Pop
    return ConfigObject.Load(StringIO(data))
149 a8083063 Iustin Pop
150 a8083063 Iustin Pop
151 5c947f38 Iustin Pop
class TaggableObject(object):
152 5c947f38 Iustin Pop
  """An generic class supporting tags.
153 5c947f38 Iustin Pop

154 5c947f38 Iustin Pop
  """
155 2057f6c7 Iustin Pop
  __slots__ = []
156 2057f6c7 Iustin Pop
157 5c947f38 Iustin Pop
  @staticmethod
158 5c947f38 Iustin Pop
  def ValidateTag(tag):
159 5c947f38 Iustin Pop
    """Check if a tag is valid.
160 5c947f38 Iustin Pop

161 5c947f38 Iustin Pop
    If the tag is invalid, an errors.TagError will be raised. The
162 5c947f38 Iustin Pop
    function has no return value.
163 5c947f38 Iustin Pop

164 5c947f38 Iustin Pop
    """
165 5c947f38 Iustin Pop
    if not isinstance(tag, basestring):
166 3ecf6786 Iustin Pop
      raise errors.TagError("Invalid tag type (not a string)")
167 5c947f38 Iustin Pop
    if len(tag) > constants.MAX_TAG_LEN:
168 3ecf6786 Iustin Pop
      raise errors.TagError("Tag too long (>%d)" % constants.MAX_TAG_LEN)
169 5c947f38 Iustin Pop
    if not tag:
170 3ecf6786 Iustin Pop
      raise errors.TagError("Tags cannot be empty")
171 5c947f38 Iustin Pop
    if not re.match("^[ \w.+*/:-]+$", tag):
172 3ecf6786 Iustin Pop
      raise errors.TagError("Tag contains invalid characters")
173 5c947f38 Iustin Pop
174 5c947f38 Iustin Pop
  def GetTags(self):
175 5c947f38 Iustin Pop
    """Return the tags list.
176 5c947f38 Iustin Pop

177 5c947f38 Iustin Pop
    """
178 5c947f38 Iustin Pop
    tags = getattr(self, "tags", None)
179 5c947f38 Iustin Pop
    if tags is None:
180 5c947f38 Iustin Pop
      tags = self.tags = set()
181 5c947f38 Iustin Pop
    return tags
182 5c947f38 Iustin Pop
183 5c947f38 Iustin Pop
  def AddTag(self, tag):
184 5c947f38 Iustin Pop
    """Add a new tag.
185 5c947f38 Iustin Pop

186 5c947f38 Iustin Pop
    """
187 5c947f38 Iustin Pop
    self.ValidateTag(tag)
188 5c947f38 Iustin Pop
    tags = self.GetTags()
189 5c947f38 Iustin Pop
    if len(tags) >= constants.MAX_TAGS_PER_OBJ:
190 3ecf6786 Iustin Pop
      raise errors.TagError("Too many tags")
191 5c947f38 Iustin Pop
    self.GetTags().add(tag)
192 5c947f38 Iustin Pop
193 5c947f38 Iustin Pop
  def RemoveTag(self, tag):
194 5c947f38 Iustin Pop
    """Remove a tag.
195 5c947f38 Iustin Pop

196 5c947f38 Iustin Pop
    """
197 5c947f38 Iustin Pop
    self.ValidateTag(tag)
198 5c947f38 Iustin Pop
    tags = self.GetTags()
199 5c947f38 Iustin Pop
    try:
200 5c947f38 Iustin Pop
      tags.remove(tag)
201 5c947f38 Iustin Pop
    except KeyError:
202 3ecf6786 Iustin Pop
      raise errors.TagError("Tag not found")
203 5c947f38 Iustin Pop
204 5c947f38 Iustin Pop
205 a8083063 Iustin Pop
class ConfigData(ConfigObject):
206 a8083063 Iustin Pop
  """Top-level config object."""
207 b2fddf63 Iustin Pop
  __slots__ = ["cluster", "nodes", "instances"]
208 a8083063 Iustin Pop
209 a8083063 Iustin Pop
210 a8083063 Iustin Pop
class NIC(ConfigObject):
211 a8083063 Iustin Pop
  """Config object representing a network card."""
212 a8083063 Iustin Pop
  __slots__ = ["mac", "ip", "bridge"]
213 a8083063 Iustin Pop
214 a8083063 Iustin Pop
215 a8083063 Iustin Pop
class Disk(ConfigObject):
216 a8083063 Iustin Pop
  """Config object representing a block device."""
217 a8083063 Iustin Pop
  __slots__ = ["dev_type", "logical_id", "physical_id",
218 a8083063 Iustin Pop
               "children", "iv_name", "size"]
219 a8083063 Iustin Pop
220 a8083063 Iustin Pop
  def CreateOnSecondary(self):
221 a8083063 Iustin Pop
    """Test if this device needs to be created on a secondary node."""
222 a8083063 Iustin Pop
    return self.dev_type in ("drbd", "lvm")
223 a8083063 Iustin Pop
224 a8083063 Iustin Pop
  def AssembleOnSecondary(self):
225 a8083063 Iustin Pop
    """Test if this device needs to be assembled on a secondary node."""
226 a8083063 Iustin Pop
    return self.dev_type in ("drbd", "lvm")
227 a8083063 Iustin Pop
228 a8083063 Iustin Pop
  def OpenOnSecondary(self):
229 a8083063 Iustin Pop
    """Test if this device needs to be opened on a secondary node."""
230 a8083063 Iustin Pop
    return self.dev_type in ("lvm",)
231 a8083063 Iustin Pop
232 a8083063 Iustin Pop
  def GetNodes(self, node):
233 a8083063 Iustin Pop
    """This function returns the nodes this device lives on.
234 a8083063 Iustin Pop

235 a8083063 Iustin Pop
    Given the node on which the parent of the device lives on (or, in
236 a8083063 Iustin Pop
    case of a top-level device, the primary node of the devices'
237 a8083063 Iustin Pop
    instance), this function will return a list of nodes on which this
238 a8083063 Iustin Pop
    devices needs to (or can) be assembled.
239 a8083063 Iustin Pop

240 a8083063 Iustin Pop
    """
241 a8083063 Iustin Pop
    if self.dev_type == "lvm" or self.dev_type == "md_raid1":
242 a8083063 Iustin Pop
      result = [node]
243 a8083063 Iustin Pop
    elif self.dev_type == "drbd":
244 a8083063 Iustin Pop
      result = [self.logical_id[0], self.logical_id[1]]
245 a8083063 Iustin Pop
      if node not in result:
246 3ecf6786 Iustin Pop
        raise errors.ConfigurationError("DRBD device passed unknown node")
247 a8083063 Iustin Pop
    else:
248 3ecf6786 Iustin Pop
      raise errors.ProgrammerError("Unhandled device type %s" % self.dev_type)
249 a8083063 Iustin Pop
    return result
250 a8083063 Iustin Pop
251 a8083063 Iustin Pop
  def ComputeNodeTree(self, parent_node):
252 a8083063 Iustin Pop
    """Compute the node/disk tree for this disk and its children.
253 a8083063 Iustin Pop

254 a8083063 Iustin Pop
    This method, given the node on which the parent disk lives, will
255 a8083063 Iustin Pop
    return the list of all (node, disk) pairs which describe the disk
256 a8083063 Iustin Pop
    tree in the most compact way. For example, a md/drbd/lvm stack
257 a8083063 Iustin Pop
    will be returned as (primary_node, md) and (secondary_node, drbd)
258 a8083063 Iustin Pop
    which represents all the top-level devices on the nodes. This
259 a8083063 Iustin Pop
    means that on the primary node we need to activate the the md (and
260 a8083063 Iustin Pop
    recursively all its children) and on the secondary node we need to
261 a8083063 Iustin Pop
    activate the drbd device (and its children, the two lvm volumes).
262 a8083063 Iustin Pop

263 a8083063 Iustin Pop
    """
264 a8083063 Iustin Pop
    my_nodes = self.GetNodes(parent_node)
265 a8083063 Iustin Pop
    result = [(node, self) for node in my_nodes]
266 a8083063 Iustin Pop
    if not self.children:
267 a8083063 Iustin Pop
      # leaf device
268 a8083063 Iustin Pop
      return result
269 a8083063 Iustin Pop
    for node in my_nodes:
270 a8083063 Iustin Pop
      for child in self.children:
271 a8083063 Iustin Pop
        child_result = child.ComputeNodeTree(node)
272 a8083063 Iustin Pop
        if len(child_result) == 1:
273 a8083063 Iustin Pop
          # child (and all its descendants) is simple, doesn't split
274 a8083063 Iustin Pop
          # over multiple hosts, so we don't need to describe it, our
275 a8083063 Iustin Pop
          # own entry for this node describes it completely
276 a8083063 Iustin Pop
          continue
277 a8083063 Iustin Pop
        else:
278 a8083063 Iustin Pop
          # check if child nodes differ from my nodes; note that
279 a8083063 Iustin Pop
          # subdisk can differ from the child itself, and be instead
280 a8083063 Iustin Pop
          # one of its descendants
281 a8083063 Iustin Pop
          for subnode, subdisk in child_result:
282 a8083063 Iustin Pop
            if subnode not in my_nodes:
283 a8083063 Iustin Pop
              result.append((subnode, subdisk))
284 a8083063 Iustin Pop
            # otherwise child is under our own node, so we ignore this
285 a8083063 Iustin Pop
            # entry (but probably the other results in the list will
286 a8083063 Iustin Pop
            # be different)
287 a8083063 Iustin Pop
    return result
288 a8083063 Iustin Pop
289 a8083063 Iustin Pop
290 5c947f38 Iustin Pop
class Instance(ConfigObject, TaggableObject):
291 a8083063 Iustin Pop
  """Config object representing an instance."""
292 a8083063 Iustin Pop
  __slots__ = [
293 a8083063 Iustin Pop
    "name",
294 a8083063 Iustin Pop
    "primary_node",
295 a8083063 Iustin Pop
    "os",
296 a8083063 Iustin Pop
    "status",
297 a8083063 Iustin Pop
    "memory",
298 a8083063 Iustin Pop
    "vcpus",
299 a8083063 Iustin Pop
    "nics",
300 a8083063 Iustin Pop
    "disks",
301 a8083063 Iustin Pop
    "disk_template",
302 5c947f38 Iustin Pop
    "tags",
303 a8083063 Iustin Pop
    ]
304 a8083063 Iustin Pop
305 a8083063 Iustin Pop
  def _ComputeSecondaryNodes(self):
306 a8083063 Iustin Pop
    """Compute the list of secondary nodes.
307 a8083063 Iustin Pop

308 a8083063 Iustin Pop
    Since the data is already there (in the drbd disks), keeping it as
309 a8083063 Iustin Pop
    a separate normal attribute is redundant and if not properly
310 a8083063 Iustin Pop
    synchronised can cause problems. Thus it's better to compute it
311 a8083063 Iustin Pop
    dynamically.
312 a8083063 Iustin Pop

313 a8083063 Iustin Pop
    """
314 a8083063 Iustin Pop
    def _Helper(primary, sec_nodes, device):
315 a8083063 Iustin Pop
      """Recursively computes secondary nodes given a top device."""
316 a8083063 Iustin Pop
      if device.dev_type == 'drbd':
317 a8083063 Iustin Pop
        nodea, nodeb, dummy = device.logical_id
318 a8083063 Iustin Pop
        if nodea == primary:
319 a8083063 Iustin Pop
          candidate = nodeb
320 a8083063 Iustin Pop
        else:
321 a8083063 Iustin Pop
          candidate = nodea
322 a8083063 Iustin Pop
        if candidate not in sec_nodes:
323 a8083063 Iustin Pop
          sec_nodes.append(candidate)
324 a8083063 Iustin Pop
      if device.children:
325 a8083063 Iustin Pop
        for child in device.children:
326 a8083063 Iustin Pop
          _Helper(primary, sec_nodes, child)
327 a8083063 Iustin Pop
328 a8083063 Iustin Pop
    secondary_nodes = []
329 a8083063 Iustin Pop
    for device in self.disks:
330 a8083063 Iustin Pop
      _Helper(self.primary_node, secondary_nodes, device)
331 a8083063 Iustin Pop
    return tuple(secondary_nodes)
332 a8083063 Iustin Pop
333 a8083063 Iustin Pop
  secondary_nodes = property(_ComputeSecondaryNodes, None, None,
334 a8083063 Iustin Pop
                             "List of secondary nodes")
335 a8083063 Iustin Pop
336 a8083063 Iustin Pop
  def MapLVsByNode(self, lvmap=None, devs=None, node=None):
337 a8083063 Iustin Pop
    """Provide a mapping of nodes to LVs this instance owns.
338 a8083063 Iustin Pop

339 a8083063 Iustin Pop
    This function figures out what logical volumes should belong on which
340 a8083063 Iustin Pop
    nodes, recursing through a device tree.
341 a8083063 Iustin Pop

342 a8083063 Iustin Pop
    Args:
343 a8083063 Iustin Pop
      lvmap: (optional) a dictionary to receive the 'node' : ['lv', ...] data.
344 a8083063 Iustin Pop

345 a8083063 Iustin Pop
    Returns:
346 a8083063 Iustin Pop
      None if lvmap arg is given.
347 a8083063 Iustin Pop
      Otherwise, { 'nodename' : ['volume1', 'volume2', ...], ... }
348 a8083063 Iustin Pop

349 a8083063 Iustin Pop
    """
350 a8083063 Iustin Pop
    if node == None:
351 a8083063 Iustin Pop
      node = self.primary_node
352 a8083063 Iustin Pop
353 a8083063 Iustin Pop
    if lvmap is None:
354 a8083063 Iustin Pop
      lvmap = { node : [] }
355 a8083063 Iustin Pop
      ret = lvmap
356 a8083063 Iustin Pop
    else:
357 a8083063 Iustin Pop
      if not node in lvmap:
358 a8083063 Iustin Pop
        lvmap[node] = []
359 a8083063 Iustin Pop
      ret = None
360 a8083063 Iustin Pop
361 a8083063 Iustin Pop
    if not devs:
362 a8083063 Iustin Pop
      devs = self.disks
363 a8083063 Iustin Pop
364 a8083063 Iustin Pop
    for dev in devs:
365 a8083063 Iustin Pop
      if dev.dev_type == "lvm":
366 a8083063 Iustin Pop
        lvmap[node].append(dev.logical_id[1])
367 a8083063 Iustin Pop
368 a8083063 Iustin Pop
      elif dev.dev_type == "drbd":
369 a8083063 Iustin Pop
        if dev.logical_id[0] not in lvmap:
370 a8083063 Iustin Pop
          lvmap[dev.logical_id[0]] = []
371 a8083063 Iustin Pop
372 a8083063 Iustin Pop
        if dev.logical_id[1] not in lvmap:
373 a8083063 Iustin Pop
          lvmap[dev.logical_id[1]] = []
374 a8083063 Iustin Pop
375 a8083063 Iustin Pop
        if dev.children:
376 a8083063 Iustin Pop
          self.MapLVsByNode(lvmap, dev.children, dev.logical_id[0])
377 a8083063 Iustin Pop
          self.MapLVsByNode(lvmap, dev.children, dev.logical_id[1])
378 a8083063 Iustin Pop
379 a8083063 Iustin Pop
      elif dev.children:
380 a8083063 Iustin Pop
        self.MapLVsByNode(lvmap, dev.children, node)
381 a8083063 Iustin Pop
382 a8083063 Iustin Pop
    return ret
383 a8083063 Iustin Pop
384 644eeef9 Iustin Pop
  def FindDisk(self, name):
385 644eeef9 Iustin Pop
    """Find a disk given having a specified name.
386 644eeef9 Iustin Pop

387 644eeef9 Iustin Pop
    This will return the disk which has the given iv_name.
388 644eeef9 Iustin Pop

389 644eeef9 Iustin Pop
    """
390 644eeef9 Iustin Pop
    for disk in self.disks:
391 644eeef9 Iustin Pop
      if disk.iv_name == name:
392 644eeef9 Iustin Pop
        return disk
393 644eeef9 Iustin Pop
394 644eeef9 Iustin Pop
    return None
395 644eeef9 Iustin Pop
396 a8083063 Iustin Pop
397 a8083063 Iustin Pop
class OS(ConfigObject):
398 a8083063 Iustin Pop
  """Config object representing an operating system."""
399 a8083063 Iustin Pop
  __slots__ = [
400 a8083063 Iustin Pop
    "name",
401 a8083063 Iustin Pop
    "path",
402 a8083063 Iustin Pop
    "api_version",
403 a8083063 Iustin Pop
    "create_script",
404 a8083063 Iustin Pop
    "export_script",
405 386b57af Iustin Pop
    "import_script",
406 386b57af Iustin Pop
    "rename_script",
407 a8083063 Iustin Pop
    ]
408 a8083063 Iustin Pop
409 a8083063 Iustin Pop
410 5c947f38 Iustin Pop
class Node(ConfigObject, TaggableObject):
411 a8083063 Iustin Pop
  """Config object representing a node."""
412 5c947f38 Iustin Pop
  __slots__ = ["name", "primary_ip", "secondary_ip", "tags"]
413 a8083063 Iustin Pop
414 a8083063 Iustin Pop
415 5c947f38 Iustin Pop
class Cluster(ConfigObject, TaggableObject):
416 a8083063 Iustin Pop
  """Config object representing the cluster."""
417 a8083063 Iustin Pop
  __slots__ = [
418 a8083063 Iustin Pop
    "config_version",
419 a8083063 Iustin Pop
    "serial_no",
420 a8083063 Iustin Pop
    "rsahostkeypub",
421 a8083063 Iustin Pop
    "highest_used_port",
422 b2fddf63 Iustin Pop
    "tcpudp_port_pool",
423 a8083063 Iustin Pop
    "mac_prefix",
424 a8083063 Iustin Pop
    "volume_group_name",
425 a8083063 Iustin Pop
    "default_bridge",
426 5c947f38 Iustin Pop
    "tags",
427 a8083063 Iustin Pop
    ]
428 a8083063 Iustin Pop
429 5c947f38 Iustin Pop
430 a8083063 Iustin Pop
class SerializableConfigParser(ConfigParser.SafeConfigParser):
431 a8083063 Iustin Pop
  """Simple wrapper over ConfigParse that allows serialization.
432 a8083063 Iustin Pop

433 a8083063 Iustin Pop
  This class is basically ConfigParser.SafeConfigParser with two
434 a8083063 Iustin Pop
  additional methods that allow it to serialize/unserialize to/from a
435 a8083063 Iustin Pop
  buffer.
436 a8083063 Iustin Pop

437 a8083063 Iustin Pop
  """
438 a8083063 Iustin Pop
  def Dumps(self):
439 a8083063 Iustin Pop
    """Dump this instance and return the string representation."""
440 a8083063 Iustin Pop
    buf = StringIO()
441 a8083063 Iustin Pop
    self.write(buf)
442 a8083063 Iustin Pop
    return buf.getvalue()
443 a8083063 Iustin Pop
444 a8083063 Iustin Pop
  @staticmethod
445 a8083063 Iustin Pop
  def Loads(data):
446 a8083063 Iustin Pop
    """Load data from a string."""
447 a8083063 Iustin Pop
    buf = StringIO(data)
448 a8083063 Iustin Pop
    cfp = SerializableConfigParser()
449 a8083063 Iustin Pop
    cfp.readfp(buf)
450 a8083063 Iustin Pop
    return cfp