Statistics
| Branch: | Tag: | Revision:

root / lib / storage.py @ 5c983ee5

History | View | Annotate | Download (12.2 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 620a85fd Iustin Pop
    if constants.SF_FREE in fields or constants.SF_SIZE in fields:
129 620a85fd Iustin Pop
      fsstats = utils.GetFilesystemStats(path)
130 ac2d0fe4 Michael Hanselmann
    else:
131 620a85fd Iustin Pop
      fsstats = 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 620a85fd Iustin Pop
        values.append(fsstats[1])
143 620a85fd Iustin Pop
144 620a85fd Iustin Pop
      elif field_name == constants.SF_SIZE:
145 620a85fd Iustin Pop
        values.append(fsstats[0])
146 620a85fd Iustin Pop
147 620a85fd Iustin Pop
      elif field_name == constants.SF_ALLOCATABLE:
148 620a85fd Iustin Pop
        values.append(True)
149 ac2d0fe4 Michael Hanselmann
150 ac2d0fe4 Michael Hanselmann
      else:
151 ac2d0fe4 Michael Hanselmann
        raise errors.StorageError("Unknown field: %r" % field_name)
152 ac2d0fe4 Michael Hanselmann
153 ac2d0fe4 Michael Hanselmann
    return values
154 ac2d0fe4 Michael Hanselmann
155 ac2d0fe4 Michael Hanselmann
156 ac2d0fe4 Michael Hanselmann
class _LvmBase(_Base):
157 ac2d0fe4 Michael Hanselmann
  """Base class for LVM storage containers.
158 ac2d0fe4 Michael Hanselmann

159 620a85fd Iustin Pop
  @cvar LIST_FIELDS: list of tuples consisting of three elements: SF_*
160 620a85fd Iustin Pop
      constants, lvm command output fields (list), and conversion
161 620a85fd Iustin Pop
      function or static value (for static value, the lvm output field
162 620a85fd Iustin Pop
      can be an empty list)
163 620a85fd Iustin Pop

164 ac2d0fe4 Michael Hanselmann
  """
165 ac2d0fe4 Michael Hanselmann
  LIST_SEP = "|"
166 ac2d0fe4 Michael Hanselmann
  LIST_COMMAND = None
167 ac2d0fe4 Michael Hanselmann
  LIST_FIELDS = None
168 ac2d0fe4 Michael Hanselmann
169 ac2d0fe4 Michael Hanselmann
  def List(self, name, wanted_field_names):
170 ac2d0fe4 Michael Hanselmann
    """Returns a list of all entities within the storage unit.
171 ac2d0fe4 Michael Hanselmann

172 ac2d0fe4 Michael Hanselmann
    See L{_Base.List}.
173 ac2d0fe4 Michael Hanselmann

174 ac2d0fe4 Michael Hanselmann
    """
175 ac2d0fe4 Michael Hanselmann
    # Get needed LVM fields
176 ac2d0fe4 Michael Hanselmann
    lvm_fields = self._GetLvmFields(self.LIST_FIELDS, wanted_field_names)
177 ac2d0fe4 Michael Hanselmann
178 ac2d0fe4 Michael Hanselmann
    # Build LVM command
179 ac2d0fe4 Michael Hanselmann
    cmd_args = self._BuildListCommand(self.LIST_COMMAND, self.LIST_SEP,
180 ac2d0fe4 Michael Hanselmann
                                      lvm_fields, name)
181 ac2d0fe4 Michael Hanselmann
182 ac2d0fe4 Michael Hanselmann
    # Run LVM command
183 ac2d0fe4 Michael Hanselmann
    cmd_result = self._RunListCommand(cmd_args)
184 ac2d0fe4 Michael Hanselmann
185 ac2d0fe4 Michael Hanselmann
    # Split and rearrange LVM command output
186 ac2d0fe4 Michael Hanselmann
    return self._BuildList(self._SplitList(cmd_result, self.LIST_SEP,
187 ac2d0fe4 Michael Hanselmann
                                           len(lvm_fields)),
188 ac2d0fe4 Michael Hanselmann
                           self.LIST_FIELDS,
189 ac2d0fe4 Michael Hanselmann
                           wanted_field_names,
190 ac2d0fe4 Michael Hanselmann
                           lvm_fields)
191 ac2d0fe4 Michael Hanselmann
192 ac2d0fe4 Michael Hanselmann
  @staticmethod
193 ac2d0fe4 Michael Hanselmann
  def _GetLvmFields(fields_def, wanted_field_names):
194 ac2d0fe4 Michael Hanselmann
    """Returns unique list of fields wanted from LVM command.
195 ac2d0fe4 Michael Hanselmann

196 ac2d0fe4 Michael Hanselmann
    @type fields_def: list
197 ac2d0fe4 Michael Hanselmann
    @param fields_def: Field definitions
198 ac2d0fe4 Michael Hanselmann
    @type wanted_field_names: list
199 ac2d0fe4 Michael Hanselmann
    @param wanted_field_names: List of requested fields
200 ac2d0fe4 Michael Hanselmann

201 ac2d0fe4 Michael Hanselmann
    """
202 ac2d0fe4 Michael Hanselmann
    field_to_idx = dict([(field_name, idx)
203 4d4a651d Michael Hanselmann
                         for (idx, (field_name, _, _)) in
204 4d4a651d Michael Hanselmann
                         enumerate(fields_def)])
205 ac2d0fe4 Michael Hanselmann
206 ac2d0fe4 Michael Hanselmann
    lvm_fields = []
207 ac2d0fe4 Michael Hanselmann
208 ac2d0fe4 Michael Hanselmann
    for field_name in wanted_field_names:
209 ac2d0fe4 Michael Hanselmann
      try:
210 ac2d0fe4 Michael Hanselmann
        idx = field_to_idx[field_name]
211 ac2d0fe4 Michael Hanselmann
      except IndexError:
212 ac2d0fe4 Michael Hanselmann
        raise errors.StorageError("Unknown field: %r" % field_name)
213 ac2d0fe4 Michael Hanselmann
214 620a85fd Iustin Pop
      (_, lvm_names, _) = fields_def[idx]
215 ac2d0fe4 Michael Hanselmann
216 620a85fd Iustin Pop
      lvm_fields.extend(lvm_names)
217 ac2d0fe4 Michael Hanselmann
218 ac2d0fe4 Michael Hanselmann
    return utils.UniqueSequence(lvm_fields)
219 ac2d0fe4 Michael Hanselmann
220 ac2d0fe4 Michael Hanselmann
  @classmethod
221 ac2d0fe4 Michael Hanselmann
  def _BuildList(cls, cmd_result, fields_def, wanted_field_names, lvm_fields):
222 ac2d0fe4 Michael Hanselmann
    """Builds the final result list.
223 ac2d0fe4 Michael Hanselmann

224 ac2d0fe4 Michael Hanselmann
    @type cmd_result: iterable
225 ac2d0fe4 Michael Hanselmann
    @param cmd_result: Iterable of LVM command output (iterable of lists)
226 ac2d0fe4 Michael Hanselmann
    @type fields_def: list
227 ac2d0fe4 Michael Hanselmann
    @param fields_def: Field definitions
228 ac2d0fe4 Michael Hanselmann
    @type wanted_field_names: list
229 ac2d0fe4 Michael Hanselmann
    @param wanted_field_names: List of requested fields
230 ac2d0fe4 Michael Hanselmann
    @type lvm_fields: list
231 ac2d0fe4 Michael Hanselmann
    @param lvm_fields: LVM fields
232 ac2d0fe4 Michael Hanselmann

233 ac2d0fe4 Michael Hanselmann
    """
234 ac2d0fe4 Michael Hanselmann
    lvm_name_to_idx = dict([(lvm_name, idx)
235 ac2d0fe4 Michael Hanselmann
                           for (idx, lvm_name) in enumerate(lvm_fields)])
236 ac2d0fe4 Michael Hanselmann
    field_to_idx = dict([(field_name, idx)
237 4d4a651d Michael Hanselmann
                         for (idx, (field_name, _, _)) in
238 4d4a651d Michael Hanselmann
                         enumerate(fields_def)])
239 ac2d0fe4 Michael Hanselmann
240 ac2d0fe4 Michael Hanselmann
    data = []
241 ac2d0fe4 Michael Hanselmann
    for raw_data in cmd_result:
242 ac2d0fe4 Michael Hanselmann
      row = []
243 ac2d0fe4 Michael Hanselmann
244 ac2d0fe4 Michael Hanselmann
      for field_name in wanted_field_names:
245 620a85fd Iustin Pop
        (_, lvm_names, mapper) = fields_def[field_to_idx[field_name]]
246 ac2d0fe4 Michael Hanselmann
247 620a85fd Iustin Pop
        values = [raw_data[lvm_name_to_idx[i]] for i in lvm_names]
248 ac2d0fe4 Michael Hanselmann
249 620a85fd Iustin Pop
        if callable(mapper):
250 620a85fd Iustin Pop
          # we got a function, call it with all the declared fields
251 620a85fd Iustin Pop
          val = mapper(*values)
252 620a85fd Iustin Pop
        elif len(values) == 1:
253 620a85fd Iustin Pop
          # we don't have a function, but we had a single field
254 620a85fd Iustin Pop
          # declared, pass it unchanged
255 620a85fd Iustin Pop
          val = values[0]
256 620a85fd Iustin Pop
        else:
257 620a85fd Iustin Pop
          # let's make sure there are no fields declared (cannot map >
258 620a85fd Iustin Pop
          # 1 field without a function)
259 620a85fd Iustin Pop
          assert not values, "LVM storage has multi-fields without a function"
260 620a85fd Iustin Pop
          val = mapper
261 ac2d0fe4 Michael Hanselmann
262 620a85fd Iustin Pop
        row.append(val)
263 ac2d0fe4 Michael Hanselmann
264 ac2d0fe4 Michael Hanselmann
      data.append(row)
265 ac2d0fe4 Michael Hanselmann
266 ac2d0fe4 Michael Hanselmann
    return data
267 ac2d0fe4 Michael Hanselmann
268 ac2d0fe4 Michael Hanselmann
  @staticmethod
269 ac2d0fe4 Michael Hanselmann
  def _BuildListCommand(cmd, sep, options, name):
270 ac2d0fe4 Michael Hanselmann
    """Builds LVM command line.
271 ac2d0fe4 Michael Hanselmann

272 ac2d0fe4 Michael Hanselmann
    @type cmd: string
273 ac2d0fe4 Michael Hanselmann
    @param cmd: Command name
274 ac2d0fe4 Michael Hanselmann
    @type sep: string
275 ac2d0fe4 Michael Hanselmann
    @param sep: Field separator character
276 ac2d0fe4 Michael Hanselmann
    @type options: list of strings
277 ac2d0fe4 Michael Hanselmann
    @param options: Wanted LVM fields
278 ac2d0fe4 Michael Hanselmann
    @type name: name or None
279 ac2d0fe4 Michael Hanselmann
    @param name: Name of requested entity
280 ac2d0fe4 Michael Hanselmann

281 ac2d0fe4 Michael Hanselmann
    """
282 ac2d0fe4 Michael Hanselmann
    args = [cmd,
283 ac2d0fe4 Michael Hanselmann
            "--noheadings", "--units=m", "--nosuffix",
284 ac2d0fe4 Michael Hanselmann
            "--separator", sep,
285 ac2d0fe4 Michael Hanselmann
            "--options", ",".join(options)]
286 ac2d0fe4 Michael Hanselmann
287 ac2d0fe4 Michael Hanselmann
    if name is not None:
288 ac2d0fe4 Michael Hanselmann
      args.append(name)
289 ac2d0fe4 Michael Hanselmann
290 ac2d0fe4 Michael Hanselmann
    return args
291 ac2d0fe4 Michael Hanselmann
292 ac2d0fe4 Michael Hanselmann
  @staticmethod
293 ac2d0fe4 Michael Hanselmann
  def _RunListCommand(args):
294 ac2d0fe4 Michael Hanselmann
    """Run LVM command.
295 ac2d0fe4 Michael Hanselmann

296 ac2d0fe4 Michael Hanselmann
    """
297 ac2d0fe4 Michael Hanselmann
    result = utils.RunCmd(args)
298 ac2d0fe4 Michael Hanselmann
299 ac2d0fe4 Michael Hanselmann
    if result.failed:
300 ac2d0fe4 Michael Hanselmann
      raise errors.StorageError("Failed to run %r, command output: %s" %
301 ac2d0fe4 Michael Hanselmann
                                (args[0], result.output))
302 ac2d0fe4 Michael Hanselmann
303 ac2d0fe4 Michael Hanselmann
    return result.stdout
304 ac2d0fe4 Michael Hanselmann
305 ac2d0fe4 Michael Hanselmann
  @staticmethod
306 ac2d0fe4 Michael Hanselmann
  def _SplitList(data, sep, fieldcount):
307 ac2d0fe4 Michael Hanselmann
    """Splits LVM command output into rows and fields.
308 ac2d0fe4 Michael Hanselmann

309 ac2d0fe4 Michael Hanselmann
    @type data: string
310 ac2d0fe4 Michael Hanselmann
    @param data: LVM command output
311 ac2d0fe4 Michael Hanselmann
    @type sep: string
312 ac2d0fe4 Michael Hanselmann
    @param sep: Field separator character
313 ac2d0fe4 Michael Hanselmann
    @type fieldcount: int
314 ac2d0fe4 Michael Hanselmann
    @param fieldcount: Expected number of fields
315 ac2d0fe4 Michael Hanselmann

316 ac2d0fe4 Michael Hanselmann
    """
317 ac2d0fe4 Michael Hanselmann
    for line in data.splitlines():
318 ac2d0fe4 Michael Hanselmann
      fields = line.strip().split(sep)
319 ac2d0fe4 Michael Hanselmann
320 ac2d0fe4 Michael Hanselmann
      if len(fields) != fieldcount:
321 620a85fd Iustin Pop
        logging.warning("Invalid line returned from lvm command: %s", line)
322 ac2d0fe4 Michael Hanselmann
        continue
323 ac2d0fe4 Michael Hanselmann
324 ac2d0fe4 Michael Hanselmann
      yield fields
325 ac2d0fe4 Michael Hanselmann
326 ac2d0fe4 Michael Hanselmann
327 ac2d0fe4 Michael Hanselmann
class LvmPvStorage(_LvmBase):
328 ac2d0fe4 Michael Hanselmann
  """LVM Physical Volume storage unit.
329 ac2d0fe4 Michael Hanselmann

330 ac2d0fe4 Michael Hanselmann
  """
331 ac2d0fe4 Michael Hanselmann
  def _GetAllocatable(attr):
332 ac2d0fe4 Michael Hanselmann
    if attr:
333 ac2d0fe4 Michael Hanselmann
      return (attr[0] == "a")
334 ac2d0fe4 Michael Hanselmann
    else:
335 ac2d0fe4 Michael Hanselmann
      logging.warning("Invalid PV attribute: %r", attr)
336 ac2d0fe4 Michael Hanselmann
      return False
337 ac2d0fe4 Michael Hanselmann
338 ac2d0fe4 Michael Hanselmann
  LIST_COMMAND = "pvs"
339 6032697c Michael Hanselmann
340 6032697c Michael Hanselmann
  # Make sure to update constants.VALID_STORAGE_FIELDS when changing field
341 6032697c Michael Hanselmann
  # definitions.
342 ac2d0fe4 Michael Hanselmann
  LIST_FIELDS = [
343 620a85fd Iustin Pop
    (constants.SF_NAME, ["pv_name"], None),
344 620a85fd Iustin Pop
    (constants.SF_SIZE, ["pv_size"], _ParseSize),
345 620a85fd Iustin Pop
    (constants.SF_USED, ["pv_used"], _ParseSize),
346 620a85fd Iustin Pop
    (constants.SF_FREE, ["pv_free"], _ParseSize),
347 620a85fd Iustin Pop
    (constants.SF_ALLOCATABLE, ["pv_attr"], _GetAllocatable),
348 ac2d0fe4 Michael Hanselmann
    ]
349 ac2d0fe4 Michael Hanselmann
350 9b648ee7 Michael Hanselmann
  def _SetAllocatable(self, name, allocatable):
351 9b648ee7 Michael Hanselmann
    """Sets the "allocatable" flag on a physical volume.
352 9b648ee7 Michael Hanselmann

353 9b648ee7 Michael Hanselmann
    @type name: string
354 9b648ee7 Michael Hanselmann
    @param name: Physical volume name
355 9b648ee7 Michael Hanselmann
    @type allocatable: bool
356 9b648ee7 Michael Hanselmann
    @param allocatable: Whether to set the "allocatable" flag
357 9b648ee7 Michael Hanselmann

358 9b648ee7 Michael Hanselmann
    """
359 9b648ee7 Michael Hanselmann
    args = ["pvchange", "--allocatable"]
360 9b648ee7 Michael Hanselmann
361 9b648ee7 Michael Hanselmann
    if allocatable:
362 9b648ee7 Michael Hanselmann
      args.append("y")
363 9b648ee7 Michael Hanselmann
    else:
364 9b648ee7 Michael Hanselmann
      args.append("n")
365 9b648ee7 Michael Hanselmann
366 9b648ee7 Michael Hanselmann
    args.append(name)
367 9b648ee7 Michael Hanselmann
368 9b648ee7 Michael Hanselmann
    result = utils.RunCmd(args)
369 9b648ee7 Michael Hanselmann
    if result.failed:
370 9b648ee7 Michael Hanselmann
      raise errors.StorageError("Failed to modify physical volume,"
371 9b648ee7 Michael Hanselmann
                                " pvchange output: %s" %
372 9b648ee7 Michael Hanselmann
                                result.output)
373 9b648ee7 Michael Hanselmann
374 9b648ee7 Michael Hanselmann
  def Modify(self, name, changes):
375 9b648ee7 Michael Hanselmann
    """Modifies flags on a physical volume.
376 9b648ee7 Michael Hanselmann

377 9b648ee7 Michael Hanselmann
    See L{_Base.Modify}.
378 9b648ee7 Michael Hanselmann

379 9b648ee7 Michael Hanselmann
    """
380 9b648ee7 Michael Hanselmann
    if constants.SF_ALLOCATABLE in changes:
381 9b648ee7 Michael Hanselmann
      self._SetAllocatable(name, changes[constants.SF_ALLOCATABLE])
382 9b648ee7 Michael Hanselmann
      del changes[constants.SF_ALLOCATABLE]
383 9b648ee7 Michael Hanselmann
384 9b648ee7 Michael Hanselmann
    # Other changes will be handled (and maybe refused) by the base class.
385 9b648ee7 Michael Hanselmann
    return _LvmBase.Modify(self, name, changes)
386 9b648ee7 Michael Hanselmann
387 ac2d0fe4 Michael Hanselmann
388 ac2d0fe4 Michael Hanselmann
class LvmVgStorage(_LvmBase):
389 ac2d0fe4 Michael Hanselmann
  """LVM Volume Group storage unit.
390 ac2d0fe4 Michael Hanselmann

391 ac2d0fe4 Michael Hanselmann
  """
392 ac2d0fe4 Michael Hanselmann
  LIST_COMMAND = "vgs"
393 6032697c Michael Hanselmann
394 6032697c Michael Hanselmann
  # Make sure to update constants.VALID_STORAGE_FIELDS when changing field
395 6032697c Michael Hanselmann
  # definitions.
396 ac2d0fe4 Michael Hanselmann
  LIST_FIELDS = [
397 620a85fd Iustin Pop
    (constants.SF_NAME, ["vg_name"], None),
398 620a85fd Iustin Pop
    (constants.SF_SIZE, ["vg_size"], _ParseSize),
399 620a85fd Iustin Pop
    (constants.SF_FREE, ["vg_free"], _ParseSize),
400 620a85fd Iustin Pop
    (constants.SF_USED, ["vg_size", "vg_free"],
401 620a85fd Iustin Pop
     lambda x, y: _ParseSize(x) - _ParseSize(y)),
402 620a85fd Iustin Pop
    (constants.SF_ALLOCATABLE, [], True),
403 ac2d0fe4 Michael Hanselmann
    ]
404 ac2d0fe4 Michael Hanselmann
405 6c3c6db9 Michael Hanselmann
  def _RemoveMissing(self, name):
406 6c3c6db9 Michael Hanselmann
    """Runs "vgreduce --removemissing" on a volume group.
407 6c3c6db9 Michael Hanselmann

408 6c3c6db9 Michael Hanselmann
    @type name: string
409 6c3c6db9 Michael Hanselmann
    @param name: Volume group name
410 6c3c6db9 Michael Hanselmann

411 6c3c6db9 Michael Hanselmann
    """
412 6c3c6db9 Michael Hanselmann
    # Ignoring vgreduce exit code. Older versions exit with an error even tough
413 6c3c6db9 Michael Hanselmann
    # the VG is already consistent. This was fixed in later versions, but we
414 6c3c6db9 Michael Hanselmann
    # cannot depend on it.
415 6c3c6db9 Michael Hanselmann
    result = utils.RunCmd(["vgreduce", "--removemissing", name])
416 6c3c6db9 Michael Hanselmann
417 6c3c6db9 Michael Hanselmann
    # Keep output in case something went wrong
418 6c3c6db9 Michael Hanselmann
    vgreduce_output = result.output
419 6c3c6db9 Michael Hanselmann
420 6c3c6db9 Michael Hanselmann
    result = utils.RunCmd(["vgs", "--noheadings", "--nosuffix", name])
421 6c3c6db9 Michael Hanselmann
    if result.failed:
422 6c3c6db9 Michael Hanselmann
      raise errors.StorageError(("Volume group '%s' still not consistent,"
423 6c3c6db9 Michael Hanselmann
                                 " 'vgreduce' output: %r,"
424 6c3c6db9 Michael Hanselmann
                                 " 'vgs' output: %r") %
425 6c3c6db9 Michael Hanselmann
                                (name, vgreduce_output, result.output))
426 6c3c6db9 Michael Hanselmann
427 6c3c6db9 Michael Hanselmann
  def Execute(self, name, op):
428 6c3c6db9 Michael Hanselmann
    """Executes an operation on a virtual volume.
429 6c3c6db9 Michael Hanselmann

430 6c3c6db9 Michael Hanselmann
    See L{_Base.Execute}.
431 6c3c6db9 Michael Hanselmann

432 6c3c6db9 Michael Hanselmann
    """
433 6c3c6db9 Michael Hanselmann
    if op == constants.SO_FIX_CONSISTENCY:
434 6c3c6db9 Michael Hanselmann
      return self._RemoveMissing(name)
435 6c3c6db9 Michael Hanselmann
436 6c3c6db9 Michael Hanselmann
    return _LvmBase.Execute(self, name, op)
437 6c3c6db9 Michael Hanselmann
438 ac2d0fe4 Michael Hanselmann
439 ac2d0fe4 Michael Hanselmann
# Lookup table for storage types
440 ac2d0fe4 Michael Hanselmann
_STORAGE_TYPES = {
441 ac2d0fe4 Michael Hanselmann
  constants.ST_FILE: FileStorage,
442 ac2d0fe4 Michael Hanselmann
  constants.ST_LVM_PV: LvmPvStorage,
443 ac2d0fe4 Michael Hanselmann
  constants.ST_LVM_VG: LvmVgStorage,
444 ac2d0fe4 Michael Hanselmann
  }
445 ac2d0fe4 Michael Hanselmann
446 ac2d0fe4 Michael Hanselmann
447 ac2d0fe4 Michael Hanselmann
def GetStorageClass(name):
448 ac2d0fe4 Michael Hanselmann
  """Returns the class for a storage type.
449 ac2d0fe4 Michael Hanselmann

450 ac2d0fe4 Michael Hanselmann
  @type name: string
451 ac2d0fe4 Michael Hanselmann
  @param name: Storage type
452 ac2d0fe4 Michael Hanselmann

453 ac2d0fe4 Michael Hanselmann
  """
454 ac2d0fe4 Michael Hanselmann
  try:
455 ac2d0fe4 Michael Hanselmann
    return _STORAGE_TYPES[name]
456 ac2d0fe4 Michael Hanselmann
  except KeyError:
457 ac2d0fe4 Michael Hanselmann
    raise errors.StorageError("Unknown storage type: %r" % name)
458 ac2d0fe4 Michael Hanselmann
459 ac2d0fe4 Michael Hanselmann
460 ac2d0fe4 Michael Hanselmann
def GetStorage(name, *args):
461 ac2d0fe4 Michael Hanselmann
  """Factory function for storage methods.
462 ac2d0fe4 Michael Hanselmann

463 ac2d0fe4 Michael Hanselmann
  @type name: string
464 ac2d0fe4 Michael Hanselmann
  @param name: Storage type
465 ac2d0fe4 Michael Hanselmann

466 ac2d0fe4 Michael Hanselmann
  """
467 ac2d0fe4 Michael Hanselmann
  return GetStorageClass(name)(*args)