Statistics
| Branch: | Tag: | Revision:

root / lib / storage.py @ 63d44c55

History | View | Annotate | Download (11 kB)

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

24 ac2d0fe4 Michael Hanselmann
"""
25 ac2d0fe4 Michael Hanselmann
26 ac2d0fe4 Michael Hanselmann
27 ac2d0fe4 Michael Hanselmann
import logging
28 ac2d0fe4 Michael Hanselmann
29 ac2d0fe4 Michael Hanselmann
from ganeti import errors
30 ac2d0fe4 Michael Hanselmann
from ganeti import constants
31 ac2d0fe4 Michael Hanselmann
from ganeti import utils
32 ac2d0fe4 Michael Hanselmann
33 ac2d0fe4 Michael Hanselmann
34 ac2d0fe4 Michael Hanselmann
def _ParseSize(value):
35 ac2d0fe4 Michael Hanselmann
  return int(round(float(value), 0))
36 ac2d0fe4 Michael Hanselmann
37 ac2d0fe4 Michael Hanselmann
38 ac2d0fe4 Michael Hanselmann
class _Base:
39 ac2d0fe4 Michael Hanselmann
  """Base class for storage abstraction.
40 ac2d0fe4 Michael Hanselmann

41 ac2d0fe4 Michael Hanselmann
  """
42 ac2d0fe4 Michael Hanselmann
  def List(self, name, fields):
43 ac2d0fe4 Michael Hanselmann
    """Returns a list of all entities within the storage unit.
44 ac2d0fe4 Michael Hanselmann

45 ac2d0fe4 Michael Hanselmann
    @type name: string or None
46 ac2d0fe4 Michael Hanselmann
    @param name: Entity name or None for all
47 ac2d0fe4 Michael Hanselmann
    @type fields: list
48 ac2d0fe4 Michael Hanselmann
    @param fields: List with all requested result fields (order is preserved)
49 ac2d0fe4 Michael Hanselmann

50 ac2d0fe4 Michael Hanselmann
    """
51 ac2d0fe4 Michael Hanselmann
    raise NotImplementedError()
52 ac2d0fe4 Michael Hanselmann
53 9b648ee7 Michael Hanselmann
  def Modify(self, name, changes):
54 9b648ee7 Michael Hanselmann
    """Modifies an entity within the storage unit.
55 9b648ee7 Michael Hanselmann

56 9b648ee7 Michael Hanselmann
    @type name: string
57 9b648ee7 Michael Hanselmann
    @param name: Entity name
58 9b648ee7 Michael Hanselmann
    @type changes: dict
59 9b648ee7 Michael Hanselmann
    @param changes: New field values
60 9b648ee7 Michael Hanselmann

61 9b648ee7 Michael Hanselmann
    """
62 9b648ee7 Michael Hanselmann
    # Don't raise an error if no changes are requested
63 9b648ee7 Michael Hanselmann
    if changes:
64 9b648ee7 Michael Hanselmann
      raise errors.ProgrammerError("Unable to modify the following"
65 9b648ee7 Michael Hanselmann
                                   "fields: %r" % (changes.keys(), ))
66 9b648ee7 Michael Hanselmann
67 4b37cac5 Michael Hanselmann
  def Execute(self, name, op):
68 4b37cac5 Michael Hanselmann
    """Executes an operation on an entity within the storage unit.
69 4b37cac5 Michael Hanselmann

70 4b37cac5 Michael Hanselmann
    @type name: string
71 4b37cac5 Michael Hanselmann
    @param name: Entity name
72 4b37cac5 Michael Hanselmann
    @type op: string
73 4b37cac5 Michael Hanselmann
    @param op: Operation name
74 4b37cac5 Michael Hanselmann

75 4b37cac5 Michael Hanselmann
    """
76 4b37cac5 Michael Hanselmann
    raise NotImplementedError()
77 4b37cac5 Michael Hanselmann
78 ac2d0fe4 Michael Hanselmann
79 ac2d0fe4 Michael Hanselmann
class FileStorage(_Base):
80 ac2d0fe4 Michael Hanselmann
  """File storage unit.
81 ac2d0fe4 Michael Hanselmann

82 ac2d0fe4 Michael Hanselmann
  """
83 ac2d0fe4 Michael Hanselmann
  def __init__(self, paths):
84 ac2d0fe4 Michael Hanselmann
    """Initializes this class.
85 ac2d0fe4 Michael Hanselmann

86 ac2d0fe4 Michael Hanselmann
    @type paths: list
87 ac2d0fe4 Michael Hanselmann
    @param paths: List of file storage paths
88 ac2d0fe4 Michael Hanselmann

89 ac2d0fe4 Michael Hanselmann
    """
90 ac2d0fe4 Michael Hanselmann
    self._paths = paths
91 ac2d0fe4 Michael Hanselmann
92 ac2d0fe4 Michael Hanselmann
  def List(self, name, fields):
93 ac2d0fe4 Michael Hanselmann
    """Returns a list of all entities within the storage unit.
94 ac2d0fe4 Michael Hanselmann

95 ac2d0fe4 Michael Hanselmann
    See L{_Base.List}.
96 ac2d0fe4 Michael Hanselmann

97 ac2d0fe4 Michael Hanselmann
    """
98 ac2d0fe4 Michael Hanselmann
    rows = []
99 ac2d0fe4 Michael Hanselmann
100 ac2d0fe4 Michael Hanselmann
    if name is None:
101 ac2d0fe4 Michael Hanselmann
      paths = self._paths
102 ac2d0fe4 Michael Hanselmann
    else:
103 ac2d0fe4 Michael Hanselmann
      paths = [name]
104 ac2d0fe4 Michael Hanselmann
105 ac2d0fe4 Michael Hanselmann
    for path in paths:
106 ac2d0fe4 Michael Hanselmann
      rows.append(self._ListInner(path, fields))
107 ac2d0fe4 Michael Hanselmann
108 ac2d0fe4 Michael Hanselmann
    return rows
109 ac2d0fe4 Michael Hanselmann
110 ac2d0fe4 Michael Hanselmann
  @staticmethod
111 ac2d0fe4 Michael Hanselmann
  def _ListInner(path, fields):
112 ac2d0fe4 Michael Hanselmann
    """Gathers requested information from directory.
113 ac2d0fe4 Michael Hanselmann

114 ac2d0fe4 Michael Hanselmann
    @type path: string
115 ac2d0fe4 Michael Hanselmann
    @param path: Path to directory
116 ac2d0fe4 Michael Hanselmann
    @type fields: list
117 ac2d0fe4 Michael Hanselmann
    @param fields: Requested fields
118 ac2d0fe4 Michael Hanselmann

119 ac2d0fe4 Michael Hanselmann
    """
120 ac2d0fe4 Michael Hanselmann
    values = []
121 ac2d0fe4 Michael Hanselmann
122 ac2d0fe4 Michael Hanselmann
    # Pre-calculate information in case it's requested more than once
123 6032697c Michael Hanselmann
    if constants.SF_USED in fields:
124 ac2d0fe4 Michael Hanselmann
      dirsize = utils.CalculateDirectorySize(path)
125 ac2d0fe4 Michael Hanselmann
    else:
126 ac2d0fe4 Michael Hanselmann
      dirsize = None
127 ac2d0fe4 Michael Hanselmann
128 6032697c Michael Hanselmann
    if constants.SF_FREE in fields:
129 ac2d0fe4 Michael Hanselmann
      fsfree = utils.GetFreeFilesystemSpace(path)
130 ac2d0fe4 Michael Hanselmann
    else:
131 ac2d0fe4 Michael Hanselmann
      fsfree = None
132 ac2d0fe4 Michael Hanselmann
133 6032697c Michael Hanselmann
    # Make sure to update constants.VALID_STORAGE_FIELDS when changing fields.
134 ac2d0fe4 Michael Hanselmann
    for field_name in fields:
135 6032697c Michael Hanselmann
      if field_name == constants.SF_NAME:
136 ac2d0fe4 Michael Hanselmann
        values.append(path)
137 ac2d0fe4 Michael Hanselmann
138 6032697c Michael Hanselmann
      elif field_name == constants.SF_USED:
139 ac2d0fe4 Michael Hanselmann
        values.append(dirsize)
140 ac2d0fe4 Michael Hanselmann
141 6032697c Michael Hanselmann
      elif field_name == constants.SF_FREE:
142 ac2d0fe4 Michael Hanselmann
        values.append(fsfree)
143 ac2d0fe4 Michael Hanselmann
144 ac2d0fe4 Michael Hanselmann
      else:
145 ac2d0fe4 Michael Hanselmann
        raise errors.StorageError("Unknown field: %r" % field_name)
146 ac2d0fe4 Michael Hanselmann
147 ac2d0fe4 Michael Hanselmann
    return values
148 ac2d0fe4 Michael Hanselmann
149 ac2d0fe4 Michael Hanselmann
150 ac2d0fe4 Michael Hanselmann
class _LvmBase(_Base):
151 ac2d0fe4 Michael Hanselmann
  """Base class for LVM storage containers.
152 ac2d0fe4 Michael Hanselmann

153 ac2d0fe4 Michael Hanselmann
  """
154 ac2d0fe4 Michael Hanselmann
  LIST_SEP = "|"
155 ac2d0fe4 Michael Hanselmann
  LIST_COMMAND = None
156 ac2d0fe4 Michael Hanselmann
  LIST_FIELDS = None
157 ac2d0fe4 Michael Hanselmann
158 ac2d0fe4 Michael Hanselmann
  def List(self, name, wanted_field_names):
159 ac2d0fe4 Michael Hanselmann
    """Returns a list of all entities within the storage unit.
160 ac2d0fe4 Michael Hanselmann

161 ac2d0fe4 Michael Hanselmann
    See L{_Base.List}.
162 ac2d0fe4 Michael Hanselmann

163 ac2d0fe4 Michael Hanselmann
    """
164 ac2d0fe4 Michael Hanselmann
    # Get needed LVM fields
165 ac2d0fe4 Michael Hanselmann
    lvm_fields = self._GetLvmFields(self.LIST_FIELDS, wanted_field_names)
166 ac2d0fe4 Michael Hanselmann
167 ac2d0fe4 Michael Hanselmann
    # Build LVM command
168 ac2d0fe4 Michael Hanselmann
    cmd_args = self._BuildListCommand(self.LIST_COMMAND, self.LIST_SEP,
169 ac2d0fe4 Michael Hanselmann
                                      lvm_fields, name)
170 ac2d0fe4 Michael Hanselmann
171 ac2d0fe4 Michael Hanselmann
    # Run LVM command
172 ac2d0fe4 Michael Hanselmann
    cmd_result = self._RunListCommand(cmd_args)
173 ac2d0fe4 Michael Hanselmann
174 ac2d0fe4 Michael Hanselmann
    # Split and rearrange LVM command output
175 ac2d0fe4 Michael Hanselmann
    return self._BuildList(self._SplitList(cmd_result, self.LIST_SEP,
176 ac2d0fe4 Michael Hanselmann
                                           len(lvm_fields)),
177 ac2d0fe4 Michael Hanselmann
                           self.LIST_FIELDS,
178 ac2d0fe4 Michael Hanselmann
                           wanted_field_names,
179 ac2d0fe4 Michael Hanselmann
                           lvm_fields)
180 ac2d0fe4 Michael Hanselmann
181 ac2d0fe4 Michael Hanselmann
  @staticmethod
182 ac2d0fe4 Michael Hanselmann
  def _GetLvmFields(fields_def, wanted_field_names):
183 ac2d0fe4 Michael Hanselmann
    """Returns unique list of fields wanted from LVM command.
184 ac2d0fe4 Michael Hanselmann

185 ac2d0fe4 Michael Hanselmann
    @type fields_def: list
186 ac2d0fe4 Michael Hanselmann
    @param fields_def: Field definitions
187 ac2d0fe4 Michael Hanselmann
    @type wanted_field_names: list
188 ac2d0fe4 Michael Hanselmann
    @param wanted_field_names: List of requested fields
189 ac2d0fe4 Michael Hanselmann

190 ac2d0fe4 Michael Hanselmann
    """
191 ac2d0fe4 Michael Hanselmann
    field_to_idx = dict([(field_name, idx)
192 ac2d0fe4 Michael Hanselmann
                         for (idx, (field_name, _, _)) in enumerate(fields_def)])
193 ac2d0fe4 Michael Hanselmann
194 ac2d0fe4 Michael Hanselmann
    lvm_fields = []
195 ac2d0fe4 Michael Hanselmann
196 ac2d0fe4 Michael Hanselmann
    for field_name in wanted_field_names:
197 ac2d0fe4 Michael Hanselmann
      try:
198 ac2d0fe4 Michael Hanselmann
        idx = field_to_idx[field_name]
199 ac2d0fe4 Michael Hanselmann
      except IndexError:
200 ac2d0fe4 Michael Hanselmann
        raise errors.StorageError("Unknown field: %r" % field_name)
201 ac2d0fe4 Michael Hanselmann
202 ac2d0fe4 Michael Hanselmann
      (_, lvm_name, _) = fields_def[idx]
203 ac2d0fe4 Michael Hanselmann
204 ac2d0fe4 Michael Hanselmann
      lvm_fields.append(lvm_name)
205 ac2d0fe4 Michael Hanselmann
206 ac2d0fe4 Michael Hanselmann
    return utils.UniqueSequence(lvm_fields)
207 ac2d0fe4 Michael Hanselmann
208 ac2d0fe4 Michael Hanselmann
  @classmethod
209 ac2d0fe4 Michael Hanselmann
  def _BuildList(cls, cmd_result, fields_def, wanted_field_names, lvm_fields):
210 ac2d0fe4 Michael Hanselmann
    """Builds the final result list.
211 ac2d0fe4 Michael Hanselmann

212 ac2d0fe4 Michael Hanselmann
    @type cmd_result: iterable
213 ac2d0fe4 Michael Hanselmann
    @param cmd_result: Iterable of LVM command output (iterable of lists)
214 ac2d0fe4 Michael Hanselmann
    @type fields_def: list
215 ac2d0fe4 Michael Hanselmann
    @param fields_def: Field definitions
216 ac2d0fe4 Michael Hanselmann
    @type wanted_field_names: list
217 ac2d0fe4 Michael Hanselmann
    @param wanted_field_names: List of requested fields
218 ac2d0fe4 Michael Hanselmann
    @type lvm_fields: list
219 ac2d0fe4 Michael Hanselmann
    @param lvm_fields: LVM fields
220 ac2d0fe4 Michael Hanselmann

221 ac2d0fe4 Michael Hanselmann
    """
222 ac2d0fe4 Michael Hanselmann
    lvm_name_to_idx = dict([(lvm_name, idx)
223 ac2d0fe4 Michael Hanselmann
                           for (idx, lvm_name) in enumerate(lvm_fields)])
224 ac2d0fe4 Michael Hanselmann
    field_to_idx = dict([(field_name, idx)
225 ac2d0fe4 Michael Hanselmann
                         for (idx, (field_name, _, _)) in enumerate(fields_def)])
226 ac2d0fe4 Michael Hanselmann
227 ac2d0fe4 Michael Hanselmann
    data = []
228 ac2d0fe4 Michael Hanselmann
    for raw_data in cmd_result:
229 ac2d0fe4 Michael Hanselmann
      row = []
230 ac2d0fe4 Michael Hanselmann
231 ac2d0fe4 Michael Hanselmann
      for field_name in wanted_field_names:
232 ac2d0fe4 Michael Hanselmann
        (_, lvm_name, convert_fn) = fields_def[field_to_idx[field_name]]
233 ac2d0fe4 Michael Hanselmann
234 ac2d0fe4 Michael Hanselmann
        value = raw_data[lvm_name_to_idx[lvm_name]]
235 ac2d0fe4 Michael Hanselmann
236 ac2d0fe4 Michael Hanselmann
        if convert_fn:
237 ac2d0fe4 Michael Hanselmann
          value = convert_fn(value)
238 ac2d0fe4 Michael Hanselmann
239 ac2d0fe4 Michael Hanselmann
        row.append(value)
240 ac2d0fe4 Michael Hanselmann
241 ac2d0fe4 Michael Hanselmann
      data.append(row)
242 ac2d0fe4 Michael Hanselmann
243 ac2d0fe4 Michael Hanselmann
    return data
244 ac2d0fe4 Michael Hanselmann
245 ac2d0fe4 Michael Hanselmann
  @staticmethod
246 ac2d0fe4 Michael Hanselmann
  def _BuildListCommand(cmd, sep, options, name):
247 ac2d0fe4 Michael Hanselmann
    """Builds LVM command line.
248 ac2d0fe4 Michael Hanselmann

249 ac2d0fe4 Michael Hanselmann
    @type cmd: string
250 ac2d0fe4 Michael Hanselmann
    @param cmd: Command name
251 ac2d0fe4 Michael Hanselmann
    @type sep: string
252 ac2d0fe4 Michael Hanselmann
    @param sep: Field separator character
253 ac2d0fe4 Michael Hanselmann
    @type options: list of strings
254 ac2d0fe4 Michael Hanselmann
    @param options: Wanted LVM fields
255 ac2d0fe4 Michael Hanselmann
    @type name: name or None
256 ac2d0fe4 Michael Hanselmann
    @param name: Name of requested entity
257 ac2d0fe4 Michael Hanselmann

258 ac2d0fe4 Michael Hanselmann
    """
259 ac2d0fe4 Michael Hanselmann
    args = [cmd,
260 ac2d0fe4 Michael Hanselmann
            "--noheadings", "--units=m", "--nosuffix",
261 ac2d0fe4 Michael Hanselmann
            "--separator", sep,
262 ac2d0fe4 Michael Hanselmann
            "--options", ",".join(options)]
263 ac2d0fe4 Michael Hanselmann
264 ac2d0fe4 Michael Hanselmann
    if name is not None:
265 ac2d0fe4 Michael Hanselmann
      args.append(name)
266 ac2d0fe4 Michael Hanselmann
267 ac2d0fe4 Michael Hanselmann
    return args
268 ac2d0fe4 Michael Hanselmann
269 ac2d0fe4 Michael Hanselmann
  @staticmethod
270 ac2d0fe4 Michael Hanselmann
  def _RunListCommand(args):
271 ac2d0fe4 Michael Hanselmann
    """Run LVM command.
272 ac2d0fe4 Michael Hanselmann

273 ac2d0fe4 Michael Hanselmann
    """
274 ac2d0fe4 Michael Hanselmann
    result = utils.RunCmd(args)
275 ac2d0fe4 Michael Hanselmann
276 ac2d0fe4 Michael Hanselmann
    if result.failed:
277 ac2d0fe4 Michael Hanselmann
      raise errors.StorageError("Failed to run %r, command output: %s" %
278 ac2d0fe4 Michael Hanselmann
                                (args[0], result.output))
279 ac2d0fe4 Michael Hanselmann
280 ac2d0fe4 Michael Hanselmann
    return result.stdout
281 ac2d0fe4 Michael Hanselmann
282 ac2d0fe4 Michael Hanselmann
  @staticmethod
283 ac2d0fe4 Michael Hanselmann
  def _SplitList(data, sep, fieldcount):
284 ac2d0fe4 Michael Hanselmann
    """Splits LVM command output into rows and fields.
285 ac2d0fe4 Michael Hanselmann

286 ac2d0fe4 Michael Hanselmann
    @type data: string
287 ac2d0fe4 Michael Hanselmann
    @param data: LVM command output
288 ac2d0fe4 Michael Hanselmann
    @type sep: string
289 ac2d0fe4 Michael Hanselmann
    @param sep: Field separator character
290 ac2d0fe4 Michael Hanselmann
    @type fieldcount: int
291 ac2d0fe4 Michael Hanselmann
    @param fieldcount: Expected number of fields
292 ac2d0fe4 Michael Hanselmann

293 ac2d0fe4 Michael Hanselmann
    """
294 ac2d0fe4 Michael Hanselmann
    for line in data.splitlines():
295 ac2d0fe4 Michael Hanselmann
      fields = line.strip().split(sep)
296 ac2d0fe4 Michael Hanselmann
297 ac2d0fe4 Michael Hanselmann
      if len(fields) != fieldcount:
298 ac2d0fe4 Michael Hanselmann
        continue
299 ac2d0fe4 Michael Hanselmann
300 ac2d0fe4 Michael Hanselmann
      yield fields
301 ac2d0fe4 Michael Hanselmann
302 ac2d0fe4 Michael Hanselmann
303 ac2d0fe4 Michael Hanselmann
class LvmPvStorage(_LvmBase):
304 ac2d0fe4 Michael Hanselmann
  """LVM Physical Volume storage unit.
305 ac2d0fe4 Michael Hanselmann

306 ac2d0fe4 Michael Hanselmann
  """
307 ac2d0fe4 Michael Hanselmann
  def _GetAllocatable(attr):
308 ac2d0fe4 Michael Hanselmann
    if attr:
309 ac2d0fe4 Michael Hanselmann
      return (attr[0] == "a")
310 ac2d0fe4 Michael Hanselmann
    else:
311 ac2d0fe4 Michael Hanselmann
      logging.warning("Invalid PV attribute: %r", attr)
312 ac2d0fe4 Michael Hanselmann
      return False
313 ac2d0fe4 Michael Hanselmann
314 ac2d0fe4 Michael Hanselmann
  LIST_COMMAND = "pvs"
315 6032697c Michael Hanselmann
316 6032697c Michael Hanselmann
  # Make sure to update constants.VALID_STORAGE_FIELDS when changing field
317 6032697c Michael Hanselmann
  # definitions.
318 ac2d0fe4 Michael Hanselmann
  LIST_FIELDS = [
319 6032697c Michael Hanselmann
    (constants.SF_NAME, "pv_name", None),
320 6032697c Michael Hanselmann
    (constants.SF_SIZE, "pv_size", _ParseSize),
321 6032697c Michael Hanselmann
    (constants.SF_USED, "pv_used", _ParseSize),
322 6032697c Michael Hanselmann
    (constants.SF_FREE, "pv_free", _ParseSize),
323 6032697c Michael Hanselmann
    (constants.SF_ALLOCATABLE, "pv_attr", _GetAllocatable),
324 ac2d0fe4 Michael Hanselmann
    ]
325 ac2d0fe4 Michael Hanselmann
326 9b648ee7 Michael Hanselmann
  def _SetAllocatable(self, name, allocatable):
327 9b648ee7 Michael Hanselmann
    """Sets the "allocatable" flag on a physical volume.
328 9b648ee7 Michael Hanselmann

329 9b648ee7 Michael Hanselmann
    @type name: string
330 9b648ee7 Michael Hanselmann
    @param name: Physical volume name
331 9b648ee7 Michael Hanselmann
    @type allocatable: bool
332 9b648ee7 Michael Hanselmann
    @param allocatable: Whether to set the "allocatable" flag
333 9b648ee7 Michael Hanselmann

334 9b648ee7 Michael Hanselmann
    """
335 9b648ee7 Michael Hanselmann
    args = ["pvchange", "--allocatable"]
336 9b648ee7 Michael Hanselmann
337 9b648ee7 Michael Hanselmann
    if allocatable:
338 9b648ee7 Michael Hanselmann
      args.append("y")
339 9b648ee7 Michael Hanselmann
    else:
340 9b648ee7 Michael Hanselmann
      args.append("n")
341 9b648ee7 Michael Hanselmann
342 9b648ee7 Michael Hanselmann
    args.append(name)
343 9b648ee7 Michael Hanselmann
344 9b648ee7 Michael Hanselmann
    result = utils.RunCmd(args)
345 9b648ee7 Michael Hanselmann
    if result.failed:
346 9b648ee7 Michael Hanselmann
      raise errors.StorageError("Failed to modify physical volume,"
347 9b648ee7 Michael Hanselmann
                                " pvchange output: %s" %
348 9b648ee7 Michael Hanselmann
                                result.output)
349 9b648ee7 Michael Hanselmann
350 9b648ee7 Michael Hanselmann
  def Modify(self, name, changes):
351 9b648ee7 Michael Hanselmann
    """Modifies flags on a physical volume.
352 9b648ee7 Michael Hanselmann

353 9b648ee7 Michael Hanselmann
    See L{_Base.Modify}.
354 9b648ee7 Michael Hanselmann

355 9b648ee7 Michael Hanselmann
    """
356 9b648ee7 Michael Hanselmann
    if constants.SF_ALLOCATABLE in changes:
357 9b648ee7 Michael Hanselmann
      self._SetAllocatable(name, changes[constants.SF_ALLOCATABLE])
358 9b648ee7 Michael Hanselmann
      del changes[constants.SF_ALLOCATABLE]
359 9b648ee7 Michael Hanselmann
360 9b648ee7 Michael Hanselmann
    # Other changes will be handled (and maybe refused) by the base class.
361 9b648ee7 Michael Hanselmann
    return _LvmBase.Modify(self, name, changes)
362 9b648ee7 Michael Hanselmann
363 ac2d0fe4 Michael Hanselmann
364 ac2d0fe4 Michael Hanselmann
class LvmVgStorage(_LvmBase):
365 ac2d0fe4 Michael Hanselmann
  """LVM Volume Group storage unit.
366 ac2d0fe4 Michael Hanselmann

367 ac2d0fe4 Michael Hanselmann
  """
368 ac2d0fe4 Michael Hanselmann
  LIST_COMMAND = "vgs"
369 6032697c Michael Hanselmann
370 6032697c Michael Hanselmann
  # Make sure to update constants.VALID_STORAGE_FIELDS when changing field
371 6032697c Michael Hanselmann
  # definitions.
372 ac2d0fe4 Michael Hanselmann
  LIST_FIELDS = [
373 6032697c Michael Hanselmann
    (constants.SF_NAME, "vg_name", None),
374 6032697c Michael Hanselmann
    (constants.SF_SIZE, "vg_size", _ParseSize),
375 ac2d0fe4 Michael Hanselmann
    ]
376 ac2d0fe4 Michael Hanselmann
377 6c3c6db9 Michael Hanselmann
  def _RemoveMissing(self, name):
378 6c3c6db9 Michael Hanselmann
    """Runs "vgreduce --removemissing" on a volume group.
379 6c3c6db9 Michael Hanselmann

380 6c3c6db9 Michael Hanselmann
    @type name: string
381 6c3c6db9 Michael Hanselmann
    @param name: Volume group name
382 6c3c6db9 Michael Hanselmann

383 6c3c6db9 Michael Hanselmann
    """
384 6c3c6db9 Michael Hanselmann
    # Ignoring vgreduce exit code. Older versions exit with an error even tough
385 6c3c6db9 Michael Hanselmann
    # the VG is already consistent. This was fixed in later versions, but we
386 6c3c6db9 Michael Hanselmann
    # cannot depend on it.
387 6c3c6db9 Michael Hanselmann
    result = utils.RunCmd(["vgreduce", "--removemissing", name])
388 6c3c6db9 Michael Hanselmann
389 6c3c6db9 Michael Hanselmann
    # Keep output in case something went wrong
390 6c3c6db9 Michael Hanselmann
    vgreduce_output = result.output
391 6c3c6db9 Michael Hanselmann
392 6c3c6db9 Michael Hanselmann
    result = utils.RunCmd(["vgs", "--noheadings", "--nosuffix", name])
393 6c3c6db9 Michael Hanselmann
    if result.failed:
394 6c3c6db9 Michael Hanselmann
      raise errors.StorageError(("Volume group '%s' still not consistent,"
395 6c3c6db9 Michael Hanselmann
                                 " 'vgreduce' output: %r,"
396 6c3c6db9 Michael Hanselmann
                                 " 'vgs' output: %r") %
397 6c3c6db9 Michael Hanselmann
                                (name, vgreduce_output, result.output))
398 6c3c6db9 Michael Hanselmann
399 6c3c6db9 Michael Hanselmann
  def Execute(self, name, op):
400 6c3c6db9 Michael Hanselmann
    """Executes an operation on a virtual volume.
401 6c3c6db9 Michael Hanselmann

402 6c3c6db9 Michael Hanselmann
    See L{_Base.Execute}.
403 6c3c6db9 Michael Hanselmann

404 6c3c6db9 Michael Hanselmann
    """
405 6c3c6db9 Michael Hanselmann
    if op == constants.SO_FIX_CONSISTENCY:
406 6c3c6db9 Michael Hanselmann
      return self._RemoveMissing(name)
407 6c3c6db9 Michael Hanselmann
408 6c3c6db9 Michael Hanselmann
    return _LvmBase.Execute(self, name, op)
409 6c3c6db9 Michael Hanselmann
410 ac2d0fe4 Michael Hanselmann
411 ac2d0fe4 Michael Hanselmann
# Lookup table for storage types
412 ac2d0fe4 Michael Hanselmann
_STORAGE_TYPES = {
413 ac2d0fe4 Michael Hanselmann
  constants.ST_FILE: FileStorage,
414 ac2d0fe4 Michael Hanselmann
  constants.ST_LVM_PV: LvmPvStorage,
415 ac2d0fe4 Michael Hanselmann
  constants.ST_LVM_VG: LvmVgStorage,
416 ac2d0fe4 Michael Hanselmann
  }
417 ac2d0fe4 Michael Hanselmann
418 ac2d0fe4 Michael Hanselmann
419 ac2d0fe4 Michael Hanselmann
def GetStorageClass(name):
420 ac2d0fe4 Michael Hanselmann
  """Returns the class for a storage type.
421 ac2d0fe4 Michael Hanselmann

422 ac2d0fe4 Michael Hanselmann
  @type name: string
423 ac2d0fe4 Michael Hanselmann
  @param name: Storage type
424 ac2d0fe4 Michael Hanselmann

425 ac2d0fe4 Michael Hanselmann
  """
426 ac2d0fe4 Michael Hanselmann
  try:
427 ac2d0fe4 Michael Hanselmann
    return _STORAGE_TYPES[name]
428 ac2d0fe4 Michael Hanselmann
  except KeyError:
429 ac2d0fe4 Michael Hanselmann
    raise errors.StorageError("Unknown storage type: %r" % name)
430 ac2d0fe4 Michael Hanselmann
431 ac2d0fe4 Michael Hanselmann
432 ac2d0fe4 Michael Hanselmann
def GetStorage(name, *args):
433 ac2d0fe4 Michael Hanselmann
  """Factory function for storage methods.
434 ac2d0fe4 Michael Hanselmann

435 ac2d0fe4 Michael Hanselmann
  @type name: string
436 ac2d0fe4 Michael Hanselmann
  @param name: Storage type
437 ac2d0fe4 Michael Hanselmann

438 ac2d0fe4 Michael Hanselmann
  """
439 ac2d0fe4 Michael Hanselmann
  return GetStorageClass(name)(*args)