Revision 577d45d4 tools/lvmstrap
b/tools/lvmstrap | ||
---|---|---|
1 | 1 |
#!/usr/bin/python |
2 | 2 |
# |
3 | 3 |
|
4 |
# Copyright (C) 2006, 2007 Google Inc. |
|
4 |
# Copyright (C) 2006, 2007, 2011 Google Inc.
|
|
5 | 5 |
# |
6 | 6 |
# This program is free software; you can redistribute it and/or modify |
7 | 7 |
# it under the terms of the GNU General Public License as published by |
... | ... | |
48 | 48 |
from ganeti.utils import RunCmd, ReadFile |
49 | 49 |
from ganeti import constants |
50 | 50 |
from ganeti import cli |
51 |
from ganeti import compat |
|
51 | 52 |
|
52 | 53 |
USAGE = ("\tlvmstrap diskinfo\n" |
53 | 54 |
"\tlvmstrap [--vgname=NAME] [--allow-removable]" |
... | ... | |
56 | 57 |
|
57 | 58 |
verbose_flag = False |
58 | 59 |
|
60 |
#: Supported disk types (as prefixes) |
|
61 |
SUPPORTED_TYPES = [ |
|
62 |
"hd", |
|
63 |
"sd", |
|
64 |
"md", |
|
65 |
"ubd", |
|
66 |
] |
|
67 |
|
|
59 | 68 |
|
60 | 69 |
class Error(Exception): |
61 | 70 |
"""Generic exception""" |
... | ... | |
169 | 178 |
return options, args |
170 | 179 |
|
171 | 180 |
|
181 |
def IsPartitioned(disk): |
|
182 |
"""Returns whether a given disk should be used partitioned or as-is. |
|
183 |
|
|
184 |
Currently only md devices are used as is. |
|
185 |
|
|
186 |
""" |
|
187 |
return not disk.startswith('md') |
|
188 |
|
|
189 |
|
|
190 |
def DeviceName(disk): |
|
191 |
"""Returns the appropriate device name for a disk. |
|
192 |
|
|
193 |
For non-partitioned devices, it returns the name as is, otherwise it |
|
194 |
returns the first partition. |
|
195 |
|
|
196 |
""" |
|
197 |
if IsPartitioned(disk): |
|
198 |
device = '/dev/%s1' % disk |
|
199 |
else: |
|
200 |
device = '/dev/%s' % disk |
|
201 |
return device |
|
202 |
|
|
203 |
|
|
172 | 204 |
def ExecCommand(command): |
173 | 205 |
"""Executes a command. |
174 | 206 |
|
... | ... | |
379 | 411 |
""" |
380 | 412 |
dlist = [] |
381 | 413 |
for name in os.listdir("/sys/block"): |
382 |
if (not name.startswith("hd") and |
|
383 |
not name.startswith("sd") and |
|
384 |
not name.startswith("ubd")): |
|
414 |
if not compat.any([name.startswith(pfx) for pfx in SUPPORTED_TYPES]): |
|
385 | 415 |
continue |
386 | 416 |
|
387 | 417 |
size = ReadSize("/sys/block/%s" % name) |
... | ... | |
534 | 564 |
def CheckReread(name): |
535 | 565 |
"""Check to see if a block device is in use. |
536 | 566 |
|
537 |
Uses blockdev to reread the partition table of a block device, and |
|
538 |
thus compute the in-use status. See the discussion in GetDiskList |
|
539 |
about the meaning of 'in use'. |
|
567 |
Uses blockdev to reread the partition table of a block device (or |
|
568 |
fuser if the device is not partitionable), and thus compute the |
|
569 |
in-use status. See the discussion in GetDiskList about the meaning |
|
570 |
of 'in use'. |
|
540 | 571 |
|
541 | 572 |
@rtype: boolean |
542 | 573 |
@return: the in-use status of the device |
543 | 574 |
|
544 | 575 |
""" |
576 |
use_blockdev = IsPartitioned(name) |
|
577 |
if use_blockdev: |
|
578 |
cmd = "blockdev --rereadpt /dev/%s" % name |
|
579 |
else: |
|
580 |
cmd = "fuser -vam /dev/%s" % name |
|
581 |
|
|
545 | 582 |
for _ in range(3): |
546 |
result = ExecCommand("blockdev --rereadpt /dev/%s" % name) |
|
547 |
if not result.failed: |
|
583 |
result = ExecCommand(cmd) |
|
584 |
if not use_blockdev and result.failed: |
|
585 |
break |
|
586 |
elif not result.failed: |
|
548 | 587 |
break |
549 | 588 |
time.sleep(2) |
550 | 589 |
|
551 |
return not result.failed |
|
590 |
if use_blockdev: |
|
591 |
return not result.failed |
|
592 |
else: |
|
593 |
return result.failed |
|
552 | 594 |
|
553 | 595 |
|
554 | 596 |
def WipeDisk(name): |
... | ... | |
623 | 665 |
@param name: the device name, e.g. sda |
624 | 666 |
|
625 | 667 |
""" |
626 |
result = ExecCommand("pvcreate -yff /dev/%s1 " % name) |
|
668 |
device = DeviceName(name) |
|
669 |
result = ExecCommand("pvcreate -yff %s" % device) |
|
627 | 670 |
if result.failed: |
628 | 671 |
raise OperationalError("I cannot create a physical volume on" |
629 |
" partition /dev/%s1. Error message: %s."
|
|
672 |
" %s. Error message: %s."
|
|
630 | 673 |
" Please clean up yourself." % |
631 |
(name, result.output))
|
|
674 |
(device, result.output))
|
|
632 | 675 |
|
633 | 676 |
|
634 | 677 |
def CreateVG(vgname, disks): |
... | ... | |
640 | 683 |
@param disks: a list of disk names, e.g. ['sda','sdb'] |
641 | 684 |
|
642 | 685 |
""" |
643 |
pnames = ["'/dev/%s1'" % disk for disk in disks]
|
|
686 |
pnames = [DeviceName(d) for d in disks]
|
|
644 | 687 |
result = ExecCommand("vgcreate -s 64MB '%s' %s" % (vgname, " ".join(pnames))) |
645 | 688 |
if result.failed: |
646 | 689 |
raise OperationalError("I cannot create the volume group %s from" |
... | ... | |
718 | 761 |
|
719 | 762 |
for disk in disklist: |
720 | 763 |
WipeDisk(disk) |
721 |
PartitionDisk(disk) |
|
764 |
if IsPartitioned(disk): |
|
765 |
PartitionDisk(disk) |
|
722 | 766 |
for disk in disklist: |
723 | 767 |
CreatePVOnDisk(disk) |
724 | 768 |
CreateVG(vgname, disklist) |
Also available in: Unified diff