#!/usr/bin/python
#
-# Copyright (C) 2006, 2007, 2011 Google Inc.
+# Copyright (C) 2006, 2007, 2011, 2012 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
USAGE = ("\tlvmstrap diskinfo\n"
"\tlvmstrap [--vg-name=NAME] [--allow-removable]"
- " { --alldisks | --disks DISKLIST }"
+ " { --alldisks | --disks DISKLIST } [--use-sfdisk]"
" create")
verbose_flag = False
]
#: Excluded filesystem types
-EXCLUDED_FS = frozenset([
+EXCLUDED_FS = compat.UniqueFrozenset([
"nfs",
"nfs4",
"autofs",
#: Minimum partition size to be considered (1 GB)
PART_MINSIZE = 1024 * 1024 * 1024
+MBR_MAX_SIZE = 2 * (10 ** 12)
class Error(Exception):
OptionParser.parse_args
"""
- global verbose_flag # pylint: disable-msg=W0603
+ global verbose_flag # pylint: disable=W0603
parser = optparse.OptionParser(usage="\n%s" % USAGE,
version="%%prog (ganeti) %s" %
parser.add_option("-g", "--vg-name", type="string",
dest="vgname", default="xenvg", metavar="NAME",
help="the volume group to be created [default: xenvg]")
-
+ parser.add_option("--use-sfdisk", dest="use_sfdisk",
+ action="store_true", default=False,
+ help="use sfdisk instead of parted")
options, args = parser.parse_args()
if len(args) != 1:
Currently only md devices are used as is.
"""
- return not (disk.startswith('md') or PART_RE.match(disk))
+ return not (disk.startswith("md") or PART_RE.match(disk))
def DeviceName(disk):
"""
if IsPartitioned(disk):
- device = '/dev/%s1' % disk
+ device = "/dev/%s1" % disk
else:
- device = '/dev/%s' % disk
+ device = "/dev/%s" % disk
return device
match = PART_RE.match(disk)
if match:
# this is a partition, which resides in /sys/block under a different name
- disk = "%s/%s" % (match.group(1), disk)
+ disk = "%s/%s" % (match.group(1), disk)
return "/sys/block/%s" % disk
raise PrereqError("This tool runs as root only. Really.")
osname, _, release, _, _ = os.uname()
- if osname != 'Linux':
+ if osname != "Linux":
raise PrereqError("This tool only runs on Linux"
" (detected OS: %s)." % osname)
- if not release.startswith("2.6."):
+ if not (release.startswith("2.6.") or release.startswith("3.")):
raise PrereqError("Wrong major kernel version (detected %s, needs"
- " 2.6.*)" % release)
+ " 2.6.* or 3.*)" % release)
if not os.path.ismount("/sys"):
raise PrereqError("Can't find a filesystem mounted at /sys."
@param name: the device name, e.g. 'sda'
@param devnum: the device number, e.g. 0x803 (2051 in decimal) for sda3
- @raises L{SysconfigError}: in case of failure of the check
+ @raises SysconfigError: in case of failure of the check
"""
path = "/dev/%s" % name
print "------- Disk information -------"
headers = {
- "name": "Name",
- "size": "Size[M]",
- "used": "Used",
- "mount": "Mount",
- "lvm": "LVM?",
- "info": "Info"
- }
+ "name": "Name",
+ "size": "Size[M]",
+ "used": "Used",
+ "mount": "Mount",
+ "lvm": "LVM?",
+ "info": "Info",
+ }
fields = ["name", "size", "used", "mount", "lvm", "info"]
flatlist = []
name)
-def PartitionDisk(name):
+def PartitionDisk(name, use_sfdisk):
"""Partitions a disk.
This function creates a single partition spanning the entire disk,
@param name: the device name, e.g. sda
"""
- result = ExecCommand(
- 'echo ,,8e, | sfdisk /dev/%s' % name)
+
+ # Check that parted exists
+ result = ExecCommand("parted --help")
if result.failed:
- raise OperationalError("CRITICAL: disk %s which I have just partitioned"
- " cannot reread its partition table, or there"
- " is some other sfdisk error. Likely, it is in"
- " use. You have to clean this yourself. Error"
- " message from sfdisk: %s" %
- (name, result.output))
+ use_sfdisk = True
+ print >> sys.stderr, ("Unable to execute \"parted --help\","
+ " falling back to sfdisk.")
+
+ # Check disk size - over 2TB means we need to use GPT
+ size = ReadSize("/sys/block/%s" % name)
+ if size > MBR_MAX_SIZE:
+ label_type = "gpt"
+ if use_sfdisk:
+ raise OperationalError("Critical: Disk larger than 2TB detected, but"
+ " parted is either not installed or --use-sfdisk"
+ " has been specified")
+ else:
+ label_type = "msdos"
+
+ if use_sfdisk:
+ result = ExecCommand(
+ "echo ,,8e, | sfdisk /dev/%s" % name)
+ if result.failed:
+ raise OperationalError("CRITICAL: disk %s which I have just partitioned"
+ " cannot reread its partition table, or there"
+ " is some other sfdisk error. Likely, it is in"
+ " use. You have to clean this yourself. Error"
+ " message from sfdisk: %s" %
+ (name, result.output))
+
+ else:
+ result = ExecCommand("parted -s /dev/%s mklabel %s" % (name, label_type))
+ if result.failed:
+ raise OperationalError("Critical: failed to create %s label on %s" %
+ (label_type, name))
+ result = ExecCommand("parted -s /dev/%s mkpart pri ext2 1 100%%" % name)
+ if result.failed:
+ raise OperationalError("Critical: failed to create partition on %s" %
+ name)
+ result = ExecCommand("parted -s /dev/%s set 1 lvm on" % name)
+ if result.failed:
+ raise OperationalError("Critical: failed to set partition on %s to LVM" %
+ name)
def CreatePVOnDisk(name):
" LV count: %s, size: %s, free: %s." %
(vgname, lv_count, vg_size, vg_free))
-
disklist = ValidateDiskList(options)
for disk in disklist:
WipeDisk(disk)
if IsPartitioned(disk):
- PartitionDisk(disk)
+ PartitionDisk(disk, options.use_sfdisk)
for disk in disklist:
CreatePVOnDisk(disk)
CreateVG(vgname, disklist)
status, lv_count, size, _ = CheckVGExists(vgname)
if status:
print "Done! %s: size %s GiB, disks: %s" % (vgname, size,
- ",".join(disklist))
+ ",".join(disklist))
else:
raise OperationalError("Although everything seemed ok, the volume"
" group did not get created.")