Revision 454723b5 tools/lvmstrap
b/tools/lvmstrap | ||
---|---|---|
36 | 36 |
usually not get these errors, but if we do it's most probably a system |
37 | 37 |
error, so they should be handled and the user instructed to report |
38 | 38 |
them. |
39 |
|
|
39 | 40 |
""" |
40 | 41 |
|
41 | 42 |
|
... | ... | |
66 | 67 |
|
67 | 68 |
This should catch sysfs tree changes, or otherwise incorrect |
68 | 69 |
assumptions about the contents of the /sys/block/... directories. |
70 |
|
|
69 | 71 |
""" |
70 | 72 |
pass |
71 | 73 |
|
... | ... | |
79 | 81 |
|
80 | 82 |
This should usually mean that the installation of the Xen node |
81 | 83 |
failed in some steps. |
84 |
|
|
82 | 85 |
""" |
83 | 86 |
pass |
84 | 87 |
|
... | ... | |
92 | 95 |
|
93 | 96 |
This should usually mean that the build steps for the Xen node were |
94 | 97 |
not followed correctly. |
98 |
|
|
95 | 99 |
""" |
96 | 100 |
pass |
97 | 101 |
|
... | ... | |
100 | 104 |
"""Exception denoting actual errors. |
101 | 105 |
|
102 | 106 |
Errors during the bootstrapping are signaled using this exception. |
107 |
|
|
103 | 108 |
""" |
104 | 109 |
pass |
105 | 110 |
|
... | ... | |
109 | 114 |
|
110 | 115 |
Wrong disks given as parameters will be signaled using this |
111 | 116 |
exception. |
117 |
|
|
112 | 118 |
""" |
113 | 119 |
pass |
114 | 120 |
|
115 | 121 |
|
116 | 122 |
def Usage(): |
117 |
"""Shows program usage information and exits the program."""
|
|
123 |
"""Shows program usage information and exits the program. |
|
118 | 124 |
|
125 |
""" |
|
119 | 126 |
print >> sys.stderr, "Usage:" |
120 | 127 |
print >> sys.stderr, USAGE |
121 | 128 |
sys.exit(2) |
... | ... | |
127 | 134 |
In case of command line errors, it will show the usage and exit the |
128 | 135 |
program. |
129 | 136 |
|
130 |
Returns: |
|
131 |
(options, args), as returned by OptionParser.parse_args |
|
137 |
@rtype: tuple |
|
138 |
@return: a tuple of (options, args), as returned by |
|
139 |
OptionParser.parse_args |
|
140 |
|
|
132 | 141 |
""" |
133 | 142 |
global verbose_flag # pylint: disable-msg=W0603 |
134 | 143 |
|
... | ... | |
167 | 176 |
difference that if the command line argument -v has been given, it |
168 | 177 |
will print the command line and the command output on stdout. |
169 | 178 |
|
170 |
Args: |
|
171 |
the command line |
|
172 |
Returns: |
|
173 |
(status, output) where status is the exit status and output the |
|
174 |
stdout and stderr of the command together |
|
175 |
""" |
|
179 |
@param command: the command line to be executed |
|
180 |
@rtype: tuple |
|
181 |
@return: a tuple of (status, output) where status is the exit status |
|
182 |
and output the stdout and stderr of the command together |
|
176 | 183 |
|
184 |
""" |
|
177 | 185 |
if verbose_flag: |
178 | 186 |
print command |
179 | 187 |
result = RunCmd(command) |
... | ... | |
187 | 195 |
|
188 | 196 |
It check that it runs on Linux 2.6, and that /sys is mounted and the |
189 | 197 |
fact that /sys/block is a directory. |
190 |
""" |
|
191 | 198 |
|
199 |
""" |
|
192 | 200 |
if os.getuid() != 0: |
193 | 201 |
raise PrereqError("This tool runs as root only. Really.") |
194 | 202 |
|
... | ... | |
220 | 228 |
def CheckVGExists(vgname): |
221 | 229 |
"""Checks to see if a volume group exists. |
222 | 230 |
|
223 |
Args: |
|
224 |
vgname: the volume group name |
|
231 |
@param vgname: the volume group name |
|
225 | 232 |
|
226 |
Returns: |
|
227 |
a four-tuple (exists, lv_count, vg_size, vg_free), where: |
|
228 |
exists: True if the volume exists, otherwise False; if False, |
|
233 |
@return: a four-tuple (exists, lv_count, vg_size, vg_free), where: |
|
234 |
- exists: True if the volume exists, otherwise False; if False, |
|
229 | 235 |
all other members of the tuple are None |
230 |
lv_count: The number of logical volumes in the volume group |
|
231 |
vg_size: The total size of the volume group (in gibibytes) |
|
232 |
vg_free: The available space in the volume group |
|
233 |
""" |
|
236 |
- lv_count: The number of logical volumes in the volume group |
|
237 |
- vg_size: The total size of the volume group (in gibibytes) |
|
238 |
- vg_free: The available space in the volume group |
|
234 | 239 |
|
240 |
""" |
|
235 | 241 |
result = ExecCommand("vgs --nohead -o lv_count,vg_size,vg_free" |
236 | 242 |
" --nosuffix --units g" |
237 | 243 |
" --ignorelockingfailure %s" % vgname) |
... | ... | |
261 | 267 |
some retries here. Since we only do a stat, we can afford to do many |
262 | 268 |
short retries. |
263 | 269 |
|
264 |
Args:
|
|
265 |
name: the device name, e.g. 'sda'
|
|
266 |
devnum: the device number, e.g. 0x803 (2051 in decimal) for sda3
|
|
270 |
@param name: the device name, e.g. 'sda'
|
|
271 |
@param devnum: the device number, e.g. 0x803 (2051 in decimal) for sda3
|
|
272 |
@raises L{SysconfigError}: in case of failure of the check
|
|
267 | 273 |
|
268 |
Returns: |
|
269 |
None; failure of the check is signaled by raising a |
|
270 |
SysconfigError exception |
|
271 | 274 |
""" |
272 |
|
|
273 | 275 |
path = "/dev/%s" % name |
274 | 276 |
for _ in range(40): |
275 | 277 |
if os.path.exists(path): |
... | ... | |
293 | 295 |
function reads that file and converts the major:minor pair to a dev |
294 | 296 |
number. |
295 | 297 |
|
296 |
Args: |
|
297 |
syspath: the path to a block device dir in sysfs, e.g. /sys/block/sda |
|
298 |
@type syspath: string |
|
299 |
@param syspath: the path to a block device dir in sysfs, |
|
300 |
e.g. C{/sys/block/sda} |
|
298 | 301 |
|
299 |
Returns: |
|
300 |
the device number |
|
301 |
""" |
|
302 |
@return: the device number |
|
302 | 303 |
|
304 |
""" |
|
303 | 305 |
if not os.path.exists("%s/dev" % syspath): |
304 | 306 |
raise ProgrammingError("Invalid path passed to ReadDev: %s" % syspath) |
305 | 307 |
f = open("%s/dev" % syspath) |
... | ... | |
320 | 322 |
function reads that file and converts the number in sectors to the |
321 | 323 |
size in bytes. |
322 | 324 |
|
323 |
Args: |
|
324 |
syspath: the path to a block device dir in sysfs, e.g. /sys/block/sda |
|
325 |
@type syspath: string |
|
326 |
@param syspath: the path to a block device dir in sysfs, |
|
327 |
e.g. C{/sys/block/sda} |
|
328 |
|
|
329 |
@rtype: int |
|
330 |
@return: the device size in bytes |
|
325 | 331 |
|
326 |
Returns: |
|
327 |
the device size in bytes |
|
328 | 332 |
""" |
329 | 333 |
|
330 | 334 |
if not os.path.exists("%s/size" % syspath): |
... | ... | |
341 | 345 |
|
342 | 346 |
This function tries to see if a block device is a physical volume. |
343 | 347 |
|
344 |
Args: |
|
345 |
dev: the device name (e.g. sda) |
|
346 |
Returns: |
|
347 |
The name of the volume group to which this PV belongs, or |
|
348 |
"" if this PV is not in use, or |
|
349 |
None if this is not a PV |
|
350 |
""" |
|
348 |
@type name: string |
|
349 |
@param name: the device name (e.g. sda) |
|
350 |
|
|
351 |
@return: the name of the volume group to which this PV belongs, or |
|
352 |
"" if this PV is not in use, or None if this is not a PV |
|
351 | 353 |
|
354 |
""" |
|
352 | 355 |
result = ExecCommand("pvdisplay -c /dev/%s" % name) |
353 | 356 |
if result.failed: |
354 | 357 |
return None |
... | ... | |
362 | 365 |
This function examines the /sys/block tree and using information |
363 | 366 |
therein, computes the status of the block device. |
364 | 367 |
|
365 |
Returns: |
|
366 |
[(name, size, dev, partitions, inuse), ...] |
|
367 |
where: |
|
368 |
name is the block device name (e.g. sda) |
|
369 |
size the size in bytes |
|
370 |
dev the device number (e.g. 8704 for hdg) |
|
371 |
partitions is [(name, size, dev), ...] mirroring the disk list data |
|
372 |
inuse is a boolean showing the in-use status of the disk, computed as the |
|
373 |
possibility of re-reading the partition table (the meaning of the |
|
374 |
operation varies with the kernel version, but is usually accurate; |
|
375 |
a mounted disk/partition or swap-area or PV with active LVs on it |
|
376 |
is busy) |
|
377 |
""" |
|
368 |
@return: a list like [(name, size, dev, partitions, inuse), ...], where: |
|
369 |
- name is the block device name (e.g. sda) |
|
370 |
- size the size in bytes |
|
371 |
- dev is the device number (e.g. 8704 for hdg) |
|
372 |
- partitions is [(name, size, dev), ...] mirroring the disk list |
|
373 |
data inuse is a boolean showing the in-use status of the disk, |
|
374 |
computed as the possibility of re-reading the partition table |
|
375 |
(the meaning of the operation varies with the kernel version, |
|
376 |
but is usually accurate; a mounted disk/partition or swap-area |
|
377 |
or PV with active LVs on it is busy) |
|
378 | 378 |
|
379 |
""" |
|
379 | 380 |
dlist = [] |
380 | 381 |
for name in os.listdir("/sys/block"): |
381 | 382 |
if (not name.startswith("hd") and |
... | ... | |
419 | 420 |
of the results is memorised for later matching against the |
420 | 421 |
/sys/block devices. |
421 | 422 |
|
422 |
Returns: |
|
423 |
a mountpoint: device number dictionary |
|
424 |
""" |
|
423 |
@rtype: dict |
|
424 |
@return: a {mountpoint: device number} dictionary |
|
425 | 425 |
|
426 |
""" |
|
426 | 427 |
mountlines = ReadFile("/proc/mounts").splitlines() |
427 | 428 |
mounts = {} |
428 | 429 |
for line in mountlines: |
... | ... | |
448 | 449 |
def DevInfo(name, dev, mountinfo): |
449 | 450 |
"""Computes miscellaneous information about a block device. |
450 | 451 |
|
451 |
Args:
|
|
452 |
name: the device name, e.g. sda
|
|
452 |
@type name: string
|
|
453 |
@param name: the device name, e.g. sda
|
|
453 | 454 |
|
454 |
Returns: |
|
455 |
(mpath, whatvg, fileinfo), where |
|
456 |
mpath is the mount path where this device is mounted or None |
|
457 |
whatvg is the result of the ReadPV function |
|
458 |
fileinfo is the output of file -bs on the device |
|
459 |
""" |
|
455 |
@return: a tuple (mpath, whatvg, fileinfo), where: |
|
456 |
- mpath is the mount path where this device is mounted or None |
|
457 |
- whatvg is the result of the ReadPV function |
|
458 |
- fileinfo is the output of file -bs on the device |
|
460 | 459 |
|
460 |
""" |
|
461 | 461 |
if dev in mountinfo: |
462 | 462 |
mpath = mountinfo[dev] |
463 | 463 |
else: |
... | ... | |
538 | 538 |
thus compute the in-use status. See the discussion in GetDiskList |
539 | 539 |
about the meaning of 'in use'. |
540 | 540 |
|
541 |
Returns: |
|
542 |
boolean, the in-use status of the device |
|
543 |
""" |
|
541 |
@rtype: boolean |
|
542 |
@return: the in-use status of the device |
|
544 | 543 |
|
544 |
""" |
|
545 | 545 |
for _ in range(3): |
546 | 546 |
result = ExecCommand("blockdev --rereadpt /dev/%s" % name) |
547 | 547 |
if not result.failed: |
... | ... | |
558 | 558 |
partition table. If not successful, it writes back the old partition |
559 | 559 |
data, and leaves the cleanup to the user. |
560 | 560 |
|
561 |
Args:
|
|
562 |
the device name (e.g. sda) |
|
561 |
@param name: the device name (e.g. sda)
|
|
562 |
|
|
563 | 563 |
""" |
564 | 564 |
|
565 | 565 |
if not CheckReread(name): |
... | ... | |
600 | 600 |
This function creates a single partition spanning the entire disk, |
601 | 601 |
by means of fdisk. |
602 | 602 |
|
603 |
Args:
|
|
604 |
the device name, e.g. sda |
|
603 |
@param name: the device name, e.g. sda
|
|
604 |
|
|
605 | 605 |
""" |
606 | 606 |
result = ExecCommand( |
607 | 607 |
'echo ,,8e, | sfdisk /dev/%s' % name) |
... | ... | |
620 | 620 |
This function creates a physical volume on a block device, overriding |
621 | 621 |
all warnings. So it can wipe existing PVs and PVs which are in a VG. |
622 | 622 |
|
623 |
Args: |
|
624 |
the device name, e.g. sda |
|
623 |
@param name: the device name, e.g. sda |
|
625 | 624 |
|
626 | 625 |
""" |
627 | 626 |
result = ExecCommand("pvcreate -yff /dev/%s1 " % name) |
... | ... | |
638 | 637 |
This function creates a volume group named `vgname` on the disks |
639 | 638 |
given as parameters. The physical extent size is set to 64MB. |
640 | 639 |
|
641 |
Args: |
|
642 |
disks: a list of disk names, e.g. ['sda','sdb'] |
|
640 |
@param disks: a list of disk names, e.g. ['sda','sdb'] |
|
643 | 641 |
|
644 | 642 |
""" |
645 | 643 |
pnames = ["'/dev/%s1'" % disk for disk in disks] |
... | ... | |
659 | 657 |
using the --disks option) such that all given disks are present and |
660 | 658 |
not in use. |
661 | 659 |
|
662 |
Args: |
|
663 |
the options returned from OptParser.parse_options |
|
660 |
@param options: the options returned from OptParser.parse_options |
|
664 | 661 |
|
665 |
Returns: |
|
666 |
a list of disk names, e.g. ['sda', 'sdb'] |
|
667 |
""" |
|
662 |
@return: a list of disk names, e.g. ['sda', 'sdb'] |
|
668 | 663 |
|
664 |
""" |
|
669 | 665 |
sysdisks = GetDiskList(options) |
670 | 666 |
if not sysdisks: |
671 | 667 |
raise PrereqError("no disks found (I looked for" |
... | ... | |
697 | 693 |
|
698 | 694 |
|
699 | 695 |
def BootStrap(): |
700 |
"""Actual main routine."""
|
|
696 |
"""Actual main routine. |
|
701 | 697 |
|
698 |
""" |
|
702 | 699 |
CheckPrereq() |
703 | 700 |
|
704 | 701 |
options, args = ParseOptions() |
... | ... | |
736 | 733 |
|
737 | 734 |
|
738 | 735 |
def main(): |
739 |
"""application entry point.
|
|
736 |
"""Application entry point.
|
|
740 | 737 |
|
741 | 738 |
This is just a wrapper over BootStrap, to handle our own exceptions. |
742 |
""" |
|
743 | 739 |
|
740 |
""" |
|
744 | 741 |
try: |
745 | 742 |
BootStrap() |
746 | 743 |
except PrereqError, err: |
Also available in: Unified diff