Statistics
| Branch: | Tag: | Revision:

root / lib / storage.py @ e4335b5b

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

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

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

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

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

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

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

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

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

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

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

355 9b648ee7 Michael Hanselmann
    See L{_Base.Modify}.
356 9b648ee7 Michael Hanselmann

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

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

382 6c3c6db9 Michael Hanselmann
    @type name: string
383 6c3c6db9 Michael Hanselmann
    @param name: Volume group name
384 6c3c6db9 Michael Hanselmann

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

404 6c3c6db9 Michael Hanselmann
    See L{_Base.Execute}.
405 6c3c6db9 Michael Hanselmann

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

424 ac2d0fe4 Michael Hanselmann
  @type name: string
425 ac2d0fe4 Michael Hanselmann
  @param name: Storage type
426 ac2d0fe4 Michael Hanselmann

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

437 ac2d0fe4 Michael Hanselmann
  @type name: string
438 ac2d0fe4 Michael Hanselmann
  @param name: Storage type
439 ac2d0fe4 Michael Hanselmann

440 ac2d0fe4 Michael Hanselmann
  """
441 ac2d0fe4 Michael Hanselmann
  return GetStorageClass(name)(*args)