root / lib / storage.py @ bf9bd8dd
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) |