/[smeserver]/cdrom.image/sme9/updates/storage/devicelibs/lvm.py
ViewVC logotype

Annotation of /cdrom.image/sme9/updates/storage/devicelibs/lvm.py

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (hide annotations) (download) (as text)
Sun Oct 20 23:12:54 2013 UTC (11 years ago) by charliebrady
Branch: MAIN
Content type: text/x-python
Add devicelibs and formats subdirectories of storage, and contained .py
files, in preparation to modifying to allow degraded RAID install.

1 charliebrady 1.1 #
2     # lvm.py
3     # lvm functions
4     #
5     # Copyright (C) 2009 Red Hat, Inc. All rights reserved.
6     #
7     # This program is free software; you can redistribute it and/or modify
8     # it under the terms of the GNU General Public License as published by
9     # the Free Software Foundation; either version 2 of the License, or
10     # (at your option) any later version.
11     #
12     # This program is distributed in the hope that it will be useful,
13     # but WITHOUT ANY WARRANTY; without even the implied warranty of
14     # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     # GNU General Public License for more details.
16     #
17     # You should have received a copy of the GNU General Public License
18     # along with this program. If not, see <http://www.gnu.org/licenses/>.
19     #
20     # Author(s): Dave Lehman <dlehman@redhat.com>
21     #
22    
23     import os
24     import math
25     import re
26    
27     import iutil
28     import logging
29     log = logging.getLogger("storage")
30    
31     from ..errors import *
32     from constants import *
33    
34     import gettext
35     _ = lambda x: gettext.ldgettext("anaconda", x)
36    
37     MAX_LV_SLOTS = 256
38    
39     def has_lvm():
40     has_lvm = False
41     for path in os.environ["PATH"].split(":"):
42     if os.access("%s/lvm" % path, os.X_OK):
43     has_lvm = True
44     break
45    
46     if has_lvm:
47     has_lvm = False
48     for line in open("/proc/devices").readlines():
49     if "device-mapper" in line.split():
50     has_lvm = True
51     break
52    
53     return has_lvm
54    
55     # Start config_args handling code
56     #
57     # Theoretically we can handle all that can be handled with the LVM --config
58     # argument. For every time we call an lvm_cc (lvm compose config) funciton
59     # we regenerate the config_args with all global info.
60     config_args = [] # Holds the final argument list
61     config_args_data = { "filterRejects": [], # regular expressions to reject.
62     "filterAccepts": [] } # regexp to accept
63    
64     def _composeConfig():
65     """lvm command accepts lvm.conf type arguments preceded by --config. """
66     global config_args, config_args_data
67     config_args = []
68    
69     filter_string = ""
70     # we don't need the accept for now.
71     # accepts = config_args_data["filterAccepts"]
72     # if len(accepts) > 0:
73     # for i in range(len(rejects)):
74     # filter_string = filter_string + ("\"a|/%s$|\", " % accepts[i])
75    
76     rejects = config_args_data["filterRejects"]
77     for reject in rejects:
78     filter_string += ("\"r|/%s$|\"," % reject)
79    
80     filter_string = " filter=[%s] " % filter_string.strip(",")
81    
82     # As we add config strings we should check them all.
83     if filter_string == "":
84     # Nothing was really done.
85     return
86    
87     # devices_string can have (inside the brackets) "dir", "scan",
88     # "preferred_names", "filter", "cache_dir", "write_cache_state",
89     # "types", "sysfs_scan", "md_component_detection". see man lvm.conf.
90     devices_string = " devices {%s} " % (filter_string) # strings can be added
91     config_string = devices_string # more strings can be added.
92     config_args = ["--config", config_string]
93    
94     def lvm_cc_addFilterRejectRegexp(regexp):
95     """ Add a regular expression to the --config string."""
96     global config_args_data
97     log.debug("lvm filter: adding %s to the reject list" % regexp)
98     config_args_data["filterRejects"].append(regexp)
99    
100     # compoes config once more.
101     _composeConfig()
102    
103     def lvm_cc_resetFilter():
104     global config_args, config_args_data
105     config_args_data["filterRejects"] = []
106     config_args_data["filterAccepts"] = []
107     config_args = []
108     # End config_args handling code.
109    
110     # Names that should not be used int the creation of VGs
111     lvm_vg_blacklist = []
112     def blacklistVG(name):
113     global lvm_vg_blacklist
114     lvm_vg_blacklist.append(name)
115    
116     def getPossiblePhysicalExtents(floor=0):
117     """Returns a list of integers representing the possible values for
118     the physical extent of a volume group. Value is in KB.
119    
120     floor - size (in KB) of smallest PE we care about.
121     """
122    
123     possiblePE = []
124     curpe = 8
125     while curpe <= 16384*1024:
126     if curpe >= floor:
127     possiblePE.append(curpe)
128     curpe = curpe * 2
129    
130     return possiblePE
131    
132     def getMaxLVSize():
133     """ Return the maximum size (in MB) of a logical volume. """
134     if iutil.getArch() in ("x86_64", "ppc64", "alpha", "ia64", "s390", "sparc"): #64bit architectures
135     return (8*1024*1024*1024*1024) #Max is 8EiB (very large number..)
136     else:
137     return (16*1024*1024) #Max is 16TiB
138    
139     # apparently lvm has a limit of 126 chars for combined vg-lv names:
140     # https://bugzilla.redhat.com/show_bug.cgi?id=747278#c6
141     # https://bugzilla.redhat.com/show_bug.cgi?id=747278#c7
142     # since dashes get escaped they count double -- allow for six of them since
143     # a dhcp-provided hostname could easily contain five dashes ("dhcp-xx-xx-xx-xx")
144     LVM_MAX_NAME_LEN = 50
145    
146     def safeLvmName(name, maxlen=LVM_MAX_NAME_LEN):
147     tmp = name.strip()
148     tmp = tmp.replace("/", "_")
149     tmp = re.sub("[^0-9a-zA-Z._]", "", tmp)
150     tmp = tmp.lstrip("_")
151    
152     if len(tmp) > maxlen:
153     tmp = tmp[:maxlen]
154    
155     return tmp
156    
157     def clampSize(size, pesize, roundup=None):
158     if roundup:
159     round = math.ceil
160     else:
161     round = math.floor
162    
163     return long(round(float(size)/float(pesize)) * pesize)
164    
165     def lvm(args, progress=None):
166     rc = iutil.execWithPulseProgress("lvm", args,
167     stdout = "/dev/tty5",
168     stderr = "/dev/tty5",
169     progress=progress)
170     if not rc:
171     return
172    
173     try:
174     msg = open("/tmp/program.log").readlines()[-1].strip()
175     except Exception:
176     msg = ""
177    
178     raise LVMError(msg)
179    
180     def pvcreate(device, progress=None):
181     # we force dataalignment=1024k since we cannot get lvm to tell us what
182     # the pe_start will be in advance
183     args = ["pvcreate"] + \
184     config_args + \
185     ["--dataalignment", "1024k"] + \
186     [device]
187    
188     try:
189     lvm(args, progress=progress)
190     except LVMError as msg:
191     raise LVMError("pvcreate failed for %s: %s" % (device, msg))
192    
193     def pvresize(device, size):
194     args = ["pvresize"] + \
195     ["--setphysicalvolumesize", ("%dm" % size)] + \
196     config_args + \
197     [device]
198    
199     try:
200     lvm(args)
201     except LVMError as msg:
202     raise LVMError("pvresize failed for %s: %s" % (device, msg))
203    
204     def pvremove(device):
205     args = ["pvremove"] + \
206     config_args + \
207     [device]
208    
209     try:
210     lvm(args)
211     except LVMError as msg:
212     raise LVMError("pvremove failed for %s: %s" % (device, msg))
213    
214     def pvinfo(device):
215     """
216     If the PV was created with '--metadacopies 0', lvm will do some
217     scanning of devices to determine from their metadata which VG
218     this PV belongs to.
219    
220     pvs -o pv_name,pv_mda_count,vg_name,vg_uuid --config \
221     'devices { scan = "/dev" filter = ["a/loop0/", "r/.*/"] }'
222     """
223     #cfg = "'devices { scan = \"/dev\" filter = [\"a/%s/\", \"r/.*/\"] }'"
224     args = ["pvs", "--noheadings"] + \
225     ["--units", "m"] + \
226     ["-o", "pv_name,pv_mda_count,vg_name,vg_uuid"] + \
227     config_args + \
228     [device]
229    
230     rc = iutil.execWithCapture("lvm", args,
231     stderr = "/dev/tty5")
232     vals = rc.split()
233     if not vals:
234     raise LVMError("pvinfo failed for %s" % device)
235    
236     # don't raise an exception if pv is not a part of any vg
237     pv_name = vals[0]
238     try:
239     vg_name, vg_uuid = vals[2], vals[3]
240     except IndexError:
241     vg_name, vg_uuid = "", ""
242    
243     info = {'pv_name': pv_name,
244     'vg_name': vg_name,
245     'vg_uuid': vg_uuid}
246    
247     return info
248    
249     def vgcreate(vg_name, pv_list, pe_size, progress=None):
250     argv = ["vgcreate"]
251     if pe_size:
252     argv.extend(["-s", "%dm" % pe_size])
253     argv.extend(config_args)
254     argv.append(vg_name)
255     argv.extend(pv_list)
256    
257     try:
258     lvm(argv, progress=progress)
259     except LVMError as msg:
260     raise LVMError("vgcreate failed for %s: %s" % (vg_name, msg))
261    
262     def vgremove(vg_name):
263     args = ["vgremove", "--force"] + \
264     config_args +\
265     [vg_name]
266    
267     try:
268     lvm(args)
269     except LVMError as msg:
270     raise LVMError("vgremove failed for %s: %s" % (vg_name, msg))
271    
272     def vgactivate(vg_name):
273     args = ["vgchange", "-a", "y"] + \
274     config_args + \
275     [vg_name]
276    
277     try:
278     lvm(args)
279     except LVMError as msg:
280     raise LVMError("vgactivate failed for %s: %s" % (vg_name, msg))
281    
282     def vgdeactivate(vg_name):
283     args = ["vgchange", "-a", "n"] + \
284     config_args + \
285     [vg_name]
286    
287     try:
288     lvm(args)
289     except LVMError as msg:
290     raise LVMError("vgdeactivate failed for %s: %s" % (vg_name, msg))
291    
292     def vgreduce(vg_name, pv_list, rm=False):
293     """ Reduce a VG.
294    
295     rm -> with RemoveMissing option.
296     Use pv_list when rm=False, otherwise ignore pv_list and call vgreduce with
297     the --removemissing option.
298     """
299     args = ["vgreduce"]
300     args.extend(config_args)
301     if rm:
302     args.extend(["--removemissing", vg_name])
303     else:
304     args.extend([vg_name] + pv_list)
305    
306     try:
307     lvm(args)
308     except LVMError as msg:
309     raise LVMError("vgreduce failed for %s: %s" % (vg_name, msg))
310    
311     def vginfo(vg_name):
312     args = ["vgs", "--noheadings", "--nosuffix"] + \
313     ["--units", "m"] + \
314     ["-o", "uuid,size,free,extent_size,extent_count,free_count,pv_count"] + \
315     config_args + \
316     [vg_name]
317    
318     buf = iutil.execWithCapture("lvm",
319     args,
320     stderr="/dev/tty5")
321     info = buf.split()
322     if len(info) != 7:
323     raise LVMError(_("vginfo failed for %s" % vg_name))
324    
325     d = {}
326     (d['uuid'],d['size'],d['free'],d['pe_size'],
327     d['pe_count'],d['pe_free'],d['pv_count']) = info
328     return d
329    
330     def lvs(vg_name):
331     args = ["lvs", "--noheadings", "--nosuffix"] + \
332     ["--units", "m"] + \
333     ["-o", "lv_name,lv_uuid,lv_size,lv_attr"] + \
334     config_args + \
335     [vg_name]
336    
337     buf = iutil.execWithCapture("lvm",
338     args,
339     stderr="/dev/tty5")
340    
341     lvs = {}
342     for line in buf.splitlines():
343     line = line.strip()
344     if not line:
345     continue
346     (name, uuid, size, attr) = line.split()
347     lvs[name] = {"size": size,
348     "uuid": uuid,
349     "attr": attr}
350    
351     if not lvs:
352     raise LVMError(_("lvs failed for %s" % vg_name))
353    
354     return lvs
355    
356     def lvorigin(vg_name, lv_name):
357     args = ["lvs", "--noheadings", "-o", "origin"] + \
358     config_args + \
359     ["%s/%s" % (vg_name, lv_name)]
360    
361     buf = iutil.execWithCapture("lvm",
362     args,
363     stderr="/dev/tty5")
364    
365     try:
366     origin = buf.splitlines()[0].strip()
367     except IndexError:
368     origin = ''
369    
370     return origin
371    
372     def lvcreate(vg_name, lv_name, size, progress=None, pvs=[]):
373     args = ["lvcreate"] + \
374     ["-L", "%dm" % size] + \
375     ["-n", lv_name] + \
376     config_args + \
377     [vg_name] + pvs
378    
379     try:
380     lvm(args, progress=progress)
381     except LVMError as msg:
382     raise LVMError("lvcreate failed for %s/%s: %s" % (vg_name, lv_name, msg))
383    
384     def lvremove(vg_name, lv_name):
385     args = ["lvremove"] + \
386     config_args + \
387     ["%s/%s" % (vg_name, lv_name)]
388    
389     try:
390     lvm(args)
391     except LVMError as msg:
392     raise LVMError("lvremove failed for %s: %s" % (lv_name, msg))
393    
394     def lvresize(vg_name, lv_name, size):
395     args = ["lvresize"] + \
396     ["--force", "-L", "%dm" % size] + \
397     config_args + \
398     ["%s/%s" % (vg_name, lv_name)]
399    
400     try:
401     lvm(args)
402     except LVMError as msg:
403     raise LVMError("lvresize failed for %s: %s" % (lv_name, msg))
404    
405     def lvactivate(vg_name, lv_name):
406     # see if lvchange accepts paths of the form 'mapper/$vg-$lv'
407     args = ["lvchange", "-a", "y"] + \
408     config_args + \
409     ["%s/%s" % (vg_name, lv_name)]
410    
411     try:
412     lvm(args)
413     except LVMError as msg:
414     raise LVMError("lvactivate failed for %s: %s" % (lv_name, msg))
415    
416     def lvdeactivate(vg_name, lv_name):
417     args = ["lvchange", "-a", "n"] + \
418     config_args + \
419     ["%s/%s" % (vg_name, lv_name)]
420    
421     try:
422     lvm(args)
423     except LVMError as msg:
424     raise LVMError("lvdeactivate failed for %s: %s" % (lv_name, msg))
425    

admin@koozali.org
ViewVC Help
Powered by ViewVC 1.2.1 RSS 2.0 feed