Statistics
| Branch: | Tag: | Revision:

root / tools / lvmstrap @ 577d45d4

History | View | Annotate | Download (24.8 kB)

1 a8083063 Iustin Pop
#!/usr/bin/python
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 577d45d4 Iustin Pop
# Copyright (C) 2006, 2007, 2011 Google Inc.
5 a8083063 Iustin Pop
#
6 a8083063 Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 a8083063 Iustin Pop
# it under the terms of the GNU General Public License as published by
8 a8083063 Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 a8083063 Iustin Pop
# (at your option) any later version.
10 a8083063 Iustin Pop
#
11 a8083063 Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 a8083063 Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 a8083063 Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 a8083063 Iustin Pop
# General Public License for more details.
15 a8083063 Iustin Pop
#
16 a8083063 Iustin Pop
# You should have received a copy of the GNU General Public License
17 a8083063 Iustin Pop
# along with this program; if not, write to the Free Software
18 a8083063 Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 a8083063 Iustin Pop
# 02110-1301, USA.
20 a8083063 Iustin Pop
21 a8083063 Iustin Pop
22 a8083063 Iustin Pop
"""Program which configures LVM on the Ganeti nodes.
23 a8083063 Iustin Pop
24 a8083063 Iustin Pop
This program wipes disks and creates a volume group on top of them. It
25 a8083063 Iustin Pop
can also show disk information to help you decide which disks you want
26 a8083063 Iustin Pop
to wipe.
27 a8083063 Iustin Pop
28 a8083063 Iustin Pop
The error handling is done by raising our own exceptions from most of
29 a8083063 Iustin Pop
the functions; these exceptions then handled globally in the main()
30 a8083063 Iustin Pop
function. The exceptions that each function can raise are not
31 a8083063 Iustin Pop
documented individually, since almost every error path ends in a
32 a8083063 Iustin Pop
raise.
33 a8083063 Iustin Pop
34 a8083063 Iustin Pop
Another two exceptions that are handled globally are IOError and
35 a8083063 Iustin Pop
OSError. The idea behind this is, since we run as root, we should
36 a8083063 Iustin Pop
usually not get these errors, but if we do it's most probably a system
37 a8083063 Iustin Pop
error, so they should be handled and the user instructed to report
38 a8083063 Iustin Pop
them.
39 454723b5 Iustin Pop
40 a8083063 Iustin Pop
"""
41 a8083063 Iustin Pop
42 a8083063 Iustin Pop
43 a8083063 Iustin Pop
import os
44 a8083063 Iustin Pop
import sys
45 a8083063 Iustin Pop
import optparse
46 a8083063 Iustin Pop
import time
47 a8083063 Iustin Pop
48 3374afa9 Guido Trotter
from ganeti.utils import RunCmd, ReadFile
49 a8083063 Iustin Pop
from ganeti import constants
50 e194129a Stephen Shirley
from ganeti import cli
51 577d45d4 Iustin Pop
from ganeti import compat
52 a8083063 Iustin Pop
53 d1687c6f Iustin Pop
USAGE = ("\tlvmstrap diskinfo\n"
54 d1687c6f Iustin Pop
         "\tlvmstrap [--vgname=NAME] [--allow-removable]"
55 d1687c6f Iustin Pop
         " { --alldisks | --disks DISKLIST }"
56 a8083063 Iustin Pop
         " create")
57 a8083063 Iustin Pop
58 a8083063 Iustin Pop
verbose_flag = False
59 a8083063 Iustin Pop
60 577d45d4 Iustin Pop
#: Supported disk types (as prefixes)
61 577d45d4 Iustin Pop
SUPPORTED_TYPES = [
62 577d45d4 Iustin Pop
  "hd",
63 577d45d4 Iustin Pop
  "sd",
64 577d45d4 Iustin Pop
  "md",
65 577d45d4 Iustin Pop
  "ubd",
66 577d45d4 Iustin Pop
  ]
67 577d45d4 Iustin Pop
68 a8083063 Iustin Pop
69 a8083063 Iustin Pop
class Error(Exception):
70 a8083063 Iustin Pop
  """Generic exception"""
71 a8083063 Iustin Pop
  pass
72 a8083063 Iustin Pop
73 a8083063 Iustin Pop
74 a8083063 Iustin Pop
class ProgrammingError(Error):
75 a8083063 Iustin Pop
  """Exception denoting invalid assumptions in programming.
76 a8083063 Iustin Pop
77 a8083063 Iustin Pop
  This should catch sysfs tree changes, or otherwise incorrect
78 a8083063 Iustin Pop
  assumptions about the contents of the /sys/block/... directories.
79 454723b5 Iustin Pop
80 a8083063 Iustin Pop
  """
81 a8083063 Iustin Pop
  pass
82 a8083063 Iustin Pop
83 a8083063 Iustin Pop
84 a8083063 Iustin Pop
class SysconfigError(Error):
85 a8083063 Iustin Pop
  """Exception denoting invalid system configuration.
86 a8083063 Iustin Pop
87 a8083063 Iustin Pop
  If the system configuration is somehow wrong (e.g. /dev files
88 a8083063 Iustin Pop
  missing, or having mismatched major/minor numbers relative to
89 a8083063 Iustin Pop
  /sys/block devices), this exception will be raised.
90 a8083063 Iustin Pop
91 a8083063 Iustin Pop
  This should usually mean that the installation of the Xen node
92 a8083063 Iustin Pop
  failed in some steps.
93 454723b5 Iustin Pop
94 a8083063 Iustin Pop
  """
95 a8083063 Iustin Pop
  pass
96 a8083063 Iustin Pop
97 a8083063 Iustin Pop
98 a8083063 Iustin Pop
class PrereqError(Error):
99 a8083063 Iustin Pop
  """Exception denoting invalid prerequisites.
100 a8083063 Iustin Pop
101 a8083063 Iustin Pop
  If the node does not meet the requirements for cluster membership, this
102 a8083063 Iustin Pop
  exception will be raised. Things like wrong kernel version, or no
103 a8083063 Iustin Pop
  free disks, etc. belong here.
104 a8083063 Iustin Pop
105 a8083063 Iustin Pop
  This should usually mean that the build steps for the Xen node were
106 a8083063 Iustin Pop
  not followed correctly.
107 454723b5 Iustin Pop
108 a8083063 Iustin Pop
  """
109 a8083063 Iustin Pop
  pass
110 a8083063 Iustin Pop
111 a8083063 Iustin Pop
112 a8083063 Iustin Pop
class OperationalError(Error):
113 a8083063 Iustin Pop
  """Exception denoting actual errors.
114 a8083063 Iustin Pop
115 a8083063 Iustin Pop
  Errors during the bootstrapping are signaled using this exception.
116 454723b5 Iustin Pop
117 a8083063 Iustin Pop
  """
118 a8083063 Iustin Pop
  pass
119 a8083063 Iustin Pop
120 a8083063 Iustin Pop
121 a8083063 Iustin Pop
class ParameterError(Error):
122 a8083063 Iustin Pop
  """Exception denoting invalid input from user.
123 a8083063 Iustin Pop
124 a8083063 Iustin Pop
  Wrong disks given as parameters will be signaled using this
125 a8083063 Iustin Pop
  exception.
126 454723b5 Iustin Pop
127 a8083063 Iustin Pop
  """
128 a8083063 Iustin Pop
  pass
129 a8083063 Iustin Pop
130 7c0d6283 Michael Hanselmann
131 a8083063 Iustin Pop
def Usage():
132 454723b5 Iustin Pop
  """Shows program usage information and exits the program.
133 a8083063 Iustin Pop
134 454723b5 Iustin Pop
  """
135 a8083063 Iustin Pop
  print >> sys.stderr, "Usage:"
136 a8083063 Iustin Pop
  print >> sys.stderr, USAGE
137 a8083063 Iustin Pop
  sys.exit(2)
138 a8083063 Iustin Pop
139 a8083063 Iustin Pop
140 a8083063 Iustin Pop
def ParseOptions():
141 a8083063 Iustin Pop
  """Parses the command line options.
142 a8083063 Iustin Pop
143 a8083063 Iustin Pop
  In case of command line errors, it will show the usage and exit the
144 a8083063 Iustin Pop
  program.
145 a8083063 Iustin Pop
146 454723b5 Iustin Pop
  @rtype: tuple
147 454723b5 Iustin Pop
  @return: a tuple of (options, args), as returned by
148 454723b5 Iustin Pop
      OptionParser.parse_args
149 454723b5 Iustin Pop
150 a8083063 Iustin Pop
  """
151 7260cfbe Iustin Pop
  global verbose_flag # pylint: disable-msg=W0603
152 a8083063 Iustin Pop
153 a8083063 Iustin Pop
  parser = optparse.OptionParser(usage="\n%s" % USAGE,
154 a8083063 Iustin Pop
                                 version="%%prog (ganeti) %s" %
155 a8083063 Iustin Pop
                                 constants.RELEASE_VERSION)
156 a8083063 Iustin Pop
157 a8083063 Iustin Pop
  parser.add_option("--alldisks", dest="alldisks",
158 a8083063 Iustin Pop
                    help="erase ALL disks", action="store_true",
159 a8083063 Iustin Pop
                    default=False)
160 a8083063 Iustin Pop
  parser.add_option("-d", "--disks", dest="disks",
161 a8083063 Iustin Pop
                    help="Choose disks (e.g. hda,hdg)",
162 a8083063 Iustin Pop
                    metavar="DISKLIST")
163 9cdb9578 Iustin Pop
  parser.add_option(cli.VERBOSE_OPT)
164 d1687c6f Iustin Pop
  parser.add_option("-r", "--allow-removable",
165 d1687c6f Iustin Pop
                    action="store_true", dest="removable_ok", default=False,
166 d1687c6f Iustin Pop
                    help="allow and use removable devices too")
167 a8083063 Iustin Pop
  parser.add_option("-g", "--vg-name", type="string",
168 a8083063 Iustin Pop
                    dest="vgname", default="xenvg", metavar="NAME",
169 a8083063 Iustin Pop
                    help="the volume group to be created [default: xenvg]")
170 a8083063 Iustin Pop
171 a8083063 Iustin Pop
172 a8083063 Iustin Pop
  options, args = parser.parse_args()
173 a8083063 Iustin Pop
  if len(args) != 1:
174 a8083063 Iustin Pop
    Usage()
175 a8083063 Iustin Pop
176 a8083063 Iustin Pop
  verbose_flag = options.verbose
177 a8083063 Iustin Pop
178 a8083063 Iustin Pop
  return options, args
179 a8083063 Iustin Pop
180 a8083063 Iustin Pop
181 577d45d4 Iustin Pop
def IsPartitioned(disk):
182 577d45d4 Iustin Pop
  """Returns whether a given disk should be used partitioned or as-is.
183 577d45d4 Iustin Pop
184 577d45d4 Iustin Pop
  Currently only md devices are used as is.
185 577d45d4 Iustin Pop
186 577d45d4 Iustin Pop
  """
187 577d45d4 Iustin Pop
  return not disk.startswith('md')
188 577d45d4 Iustin Pop
189 577d45d4 Iustin Pop
190 577d45d4 Iustin Pop
def DeviceName(disk):
191 577d45d4 Iustin Pop
  """Returns the appropriate device name for a disk.
192 577d45d4 Iustin Pop
193 577d45d4 Iustin Pop
  For non-partitioned devices, it returns the name as is, otherwise it
194 577d45d4 Iustin Pop
  returns the first partition.
195 577d45d4 Iustin Pop
196 577d45d4 Iustin Pop
  """
197 577d45d4 Iustin Pop
  if IsPartitioned(disk):
198 577d45d4 Iustin Pop
    device = '/dev/%s1' % disk
199 577d45d4 Iustin Pop
  else:
200 577d45d4 Iustin Pop
    device = '/dev/%s' % disk
201 577d45d4 Iustin Pop
  return device
202 577d45d4 Iustin Pop
203 577d45d4 Iustin Pop
204 a8083063 Iustin Pop
def ExecCommand(command):
205 a8083063 Iustin Pop
  """Executes a command.
206 a8083063 Iustin Pop
207 a8083063 Iustin Pop
  This is just a wrapper around commands.getstatusoutput, with the
208 a8083063 Iustin Pop
  difference that if the command line argument -v has been given, it
209 a8083063 Iustin Pop
  will print the command line and the command output on stdout.
210 a8083063 Iustin Pop
211 454723b5 Iustin Pop
  @param command: the command line to be executed
212 454723b5 Iustin Pop
  @rtype: tuple
213 454723b5 Iustin Pop
  @return: a tuple of (status, output) where status is the exit status
214 454723b5 Iustin Pop
      and output the stdout and stderr of the command together
215 a8083063 Iustin Pop
216 454723b5 Iustin Pop
  """
217 a8083063 Iustin Pop
  if verbose_flag:
218 a8083063 Iustin Pop
    print command
219 a8083063 Iustin Pop
  result = RunCmd(command)
220 a8083063 Iustin Pop
  if verbose_flag:
221 a8083063 Iustin Pop
    print result.output
222 a8083063 Iustin Pop
  return result
223 a8083063 Iustin Pop
224 a8083063 Iustin Pop
225 a8083063 Iustin Pop
def CheckPrereq():
226 a8083063 Iustin Pop
  """Check the prerequisites of this program.
227 a8083063 Iustin Pop
228 a8083063 Iustin Pop
  It check that it runs on Linux 2.6, and that /sys is mounted and the
229 a8083063 Iustin Pop
  fact that /sys/block is a directory.
230 a8083063 Iustin Pop
231 454723b5 Iustin Pop
  """
232 a8083063 Iustin Pop
  if os.getuid() != 0:
233 a8083063 Iustin Pop
    raise PrereqError("This tool runs as root only. Really.")
234 a8083063 Iustin Pop
235 f4ad2ef0 Iustin Pop
  osname, _, release, _, _ = os.uname()
236 a8083063 Iustin Pop
  if osname != 'Linux':
237 f4bc1f2c Michael Hanselmann
    raise PrereqError("This tool only runs on Linux"
238 f4bc1f2c Michael Hanselmann
                      " (detected OS: %s)." % osname)
239 a8083063 Iustin Pop
240 a8083063 Iustin Pop
  if not release.startswith("2.6."):
241 f4bc1f2c Michael Hanselmann
    raise PrereqError("Wrong major kernel version (detected %s, needs"
242 f4bc1f2c Michael Hanselmann
                      " 2.6.*)" % release)
243 a8083063 Iustin Pop
244 a8083063 Iustin Pop
  if not os.path.ismount("/sys"):
245 f4bc1f2c Michael Hanselmann
    raise PrereqError("Can't find a filesystem mounted at /sys."
246 f4bc1f2c Michael Hanselmann
                      " Please mount /sys.")
247 a8083063 Iustin Pop
248 a8083063 Iustin Pop
  if not os.path.isdir("/sys/block"):
249 f4bc1f2c Michael Hanselmann
    raise SysconfigError("Can't find /sys/block directory. Has the"
250 f4bc1f2c Michael Hanselmann
                         " layout of /sys changed?")
251 a8083063 Iustin Pop
252 a8083063 Iustin Pop
  if not os.path.ismount("/proc"):
253 f4bc1f2c Michael Hanselmann
    raise PrereqError("Can't find a filesystem mounted at /proc."
254 f4bc1f2c Michael Hanselmann
                      " Please mount /proc.")
255 a8083063 Iustin Pop
256 a8083063 Iustin Pop
  if not os.path.exists("/proc/mounts"):
257 a8083063 Iustin Pop
    raise SysconfigError("Can't find /proc/mounts")
258 a8083063 Iustin Pop
259 a8083063 Iustin Pop
260 a8083063 Iustin Pop
def CheckVGExists(vgname):
261 a8083063 Iustin Pop
  """Checks to see if a volume group exists.
262 a8083063 Iustin Pop
263 454723b5 Iustin Pop
  @param vgname: the volume group name
264 a8083063 Iustin Pop
265 454723b5 Iustin Pop
  @return: a four-tuple (exists, lv_count, vg_size, vg_free), where:
266 454723b5 Iustin Pop
      - exists: True if the volume exists, otherwise False; if False,
267 a8083063 Iustin Pop
        all other members of the tuple are None
268 454723b5 Iustin Pop
      - lv_count: The number of logical volumes in the volume group
269 454723b5 Iustin Pop
      - vg_size: The total size of the volume group (in gibibytes)
270 454723b5 Iustin Pop
      - vg_free: The available space in the volume group
271 a8083063 Iustin Pop
272 454723b5 Iustin Pop
  """
273 f4bc1f2c Michael Hanselmann
  result = ExecCommand("vgs --nohead -o lv_count,vg_size,vg_free"
274 f4bc1f2c Michael Hanselmann
                       " --nosuffix --units g"
275 f4bc1f2c Michael Hanselmann
                       " --ignorelockingfailure %s" % vgname)
276 a8083063 Iustin Pop
  if not result.failed:
277 a8083063 Iustin Pop
    try:
278 a8083063 Iustin Pop
      lv_count, vg_size, vg_free = result.stdout.strip().split()
279 a8083063 Iustin Pop
    except ValueError:
280 a8083063 Iustin Pop
      # This means the output of vgdisplay can't be parsed
281 a8083063 Iustin Pop
      raise PrereqError("cannot parse output of vgs (%s)" % result.stdout)
282 a8083063 Iustin Pop
  else:
283 a8083063 Iustin Pop
    lv_count = vg_size = vg_free = None
284 a8083063 Iustin Pop
285 a8083063 Iustin Pop
  return not result.failed, lv_count, vg_size, vg_free
286 a8083063 Iustin Pop
287 a8083063 Iustin Pop
288 a8083063 Iustin Pop
def CheckSysDev(name, devnum):
289 a8083063 Iustin Pop
  """Checks consistency between /sys and /dev trees.
290 a8083063 Iustin Pop
291 a8083063 Iustin Pop
  In /sys/block/<name>/dev and /sys/block/<name>/<part>/dev are the
292 a8083063 Iustin Pop
  kernel-known device numbers. The /dev/<name> block/char devices are
293 a8083063 Iustin Pop
  created by userspace and thus could differ from the kernel
294 a8083063 Iustin Pop
  view. This function checks the consistency between the device number
295 a8083063 Iustin Pop
  read from /sys and the actual device number in /dev.
296 a8083063 Iustin Pop
297 a8083063 Iustin Pop
  Note that since the system could be using udev which removes and
298 a8083063 Iustin Pop
  recreates the device nodes on partition table rescan, we need to do
299 a8083063 Iustin Pop
  some retries here. Since we only do a stat, we can afford to do many
300 a8083063 Iustin Pop
  short retries.
301 a8083063 Iustin Pop
302 454723b5 Iustin Pop
  @param name: the device name, e.g. 'sda'
303 454723b5 Iustin Pop
  @param devnum: the device number, e.g. 0x803 (2051 in decimal) for sda3
304 454723b5 Iustin Pop
  @raises L{SysconfigError}: in case of failure of the check
305 a8083063 Iustin Pop
306 a8083063 Iustin Pop
  """
307 a8083063 Iustin Pop
  path = "/dev/%s" % name
308 f4ad2ef0 Iustin Pop
  for _ in range(40):
309 a8083063 Iustin Pop
    if os.path.exists(path):
310 a8083063 Iustin Pop
      break
311 a8083063 Iustin Pop
    time.sleep(0.250)
312 a8083063 Iustin Pop
  else:
313 f4bc1f2c Michael Hanselmann
    raise SysconfigError("the device file %s does not exist, but the block"
314 f4bc1f2c Michael Hanselmann
                         " device exists in the /sys/block tree" % path)
315 a8083063 Iustin Pop
  rdev = os.stat(path).st_rdev
316 a8083063 Iustin Pop
  if devnum != rdev:
317 f4bc1f2c Michael Hanselmann
    raise SysconfigError("For device %s, the major:minor in /dev is %04x"
318 f4bc1f2c Michael Hanselmann
                         " while the major:minor in sysfs is %s" %
319 a8083063 Iustin Pop
                         (path, rdev, devnum))
320 a8083063 Iustin Pop
321 a8083063 Iustin Pop
322 a8083063 Iustin Pop
def ReadDev(syspath):
323 a8083063 Iustin Pop
  """Reads the device number from a sysfs path.
324 a8083063 Iustin Pop
325 a8083063 Iustin Pop
  The device number is given in sysfs under a block device directory
326 a8083063 Iustin Pop
  in a file named 'dev' which contains major:minor (in ASCII). This
327 a8083063 Iustin Pop
  function reads that file and converts the major:minor pair to a dev
328 a8083063 Iustin Pop
  number.
329 a8083063 Iustin Pop
330 454723b5 Iustin Pop
  @type syspath: string
331 454723b5 Iustin Pop
  @param syspath: the path to a block device dir in sysfs,
332 454723b5 Iustin Pop
      e.g. C{/sys/block/sda}
333 a8083063 Iustin Pop
334 454723b5 Iustin Pop
  @return: the device number
335 a8083063 Iustin Pop
336 454723b5 Iustin Pop
  """
337 a8083063 Iustin Pop
  if not os.path.exists("%s/dev" % syspath):
338 a8083063 Iustin Pop
    raise ProgrammingError("Invalid path passed to ReadDev: %s" % syspath)
339 a8083063 Iustin Pop
  f = open("%s/dev" % syspath)
340 a8083063 Iustin Pop
  data = f.read().strip()
341 a8083063 Iustin Pop
  f.close()
342 a8083063 Iustin Pop
  major, minor = data.split(":", 1)
343 a8083063 Iustin Pop
  major = int(major)
344 a8083063 Iustin Pop
  minor = int(minor)
345 a8083063 Iustin Pop
  dev = os.makedev(major, minor)
346 a8083063 Iustin Pop
  return dev
347 a8083063 Iustin Pop
348 a8083063 Iustin Pop
349 a8083063 Iustin Pop
def ReadSize(syspath):
350 a8083063 Iustin Pop
  """Reads the size from a sysfs path.
351 a8083063 Iustin Pop
352 a8083063 Iustin Pop
  The size is given in sysfs under a block device directory in a file
353 a8083063 Iustin Pop
  named 'size' which contains the number of sectors (in ASCII). This
354 a8083063 Iustin Pop
  function reads that file and converts the number in sectors to the
355 a8083063 Iustin Pop
  size in bytes.
356 a8083063 Iustin Pop
357 454723b5 Iustin Pop
  @type syspath: string
358 454723b5 Iustin Pop
  @param syspath: the path to a block device dir in sysfs,
359 454723b5 Iustin Pop
      e.g. C{/sys/block/sda}
360 454723b5 Iustin Pop
361 454723b5 Iustin Pop
  @rtype: int
362 454723b5 Iustin Pop
  @return: the device size in bytes
363 a8083063 Iustin Pop
364 a8083063 Iustin Pop
  """
365 a8083063 Iustin Pop
366 a8083063 Iustin Pop
  if not os.path.exists("%s/size" % syspath):
367 a8083063 Iustin Pop
    raise ProgrammingError("Invalid path passed to ReadSize: %s" % syspath)
368 a8083063 Iustin Pop
  f = open("%s/size" % syspath)
369 a8083063 Iustin Pop
  data = f.read().strip()
370 a8083063 Iustin Pop
  f.close()
371 a8083063 Iustin Pop
  size = 512L * int(data)
372 a8083063 Iustin Pop
  return size
373 a8083063 Iustin Pop
374 a8083063 Iustin Pop
375 a8083063 Iustin Pop
def ReadPV(name):
376 a8083063 Iustin Pop
  """Reads physical volume information.
377 a8083063 Iustin Pop
378 a8083063 Iustin Pop
  This function tries to see if a block device is a physical volume.
379 a8083063 Iustin Pop
380 454723b5 Iustin Pop
  @type name: string
381 454723b5 Iustin Pop
  @param name: the device name (e.g. sda)
382 454723b5 Iustin Pop
383 454723b5 Iustin Pop
  @return: the name of the volume group to which this PV belongs, or
384 454723b5 Iustin Pop
      "" if this PV is not in use, or None if this is not a PV
385 a8083063 Iustin Pop
386 454723b5 Iustin Pop
  """
387 a8083063 Iustin Pop
  result = ExecCommand("pvdisplay -c /dev/%s" % name)
388 a8083063 Iustin Pop
  if result.failed:
389 a8083063 Iustin Pop
    return None
390 a8083063 Iustin Pop
  vgname = result.stdout.strip().split(":")[1]
391 a8083063 Iustin Pop
  return vgname
392 a8083063 Iustin Pop
393 a8083063 Iustin Pop
394 d1687c6f Iustin Pop
def GetDiskList(opts):
395 a8083063 Iustin Pop
  """Computes the block device list for this system.
396 a8083063 Iustin Pop
397 a8083063 Iustin Pop
  This function examines the /sys/block tree and using information
398 a8083063 Iustin Pop
  therein, computes the status of the block device.
399 a8083063 Iustin Pop
400 454723b5 Iustin Pop
  @return: a list like [(name, size, dev, partitions, inuse), ...], where:
401 454723b5 Iustin Pop
      - name is the block device name (e.g. sda)
402 454723b5 Iustin Pop
      - size the size in bytes
403 454723b5 Iustin Pop
      - dev is the device number (e.g. 8704 for hdg)
404 454723b5 Iustin Pop
      - partitions is [(name, size, dev), ...] mirroring the disk list
405 454723b5 Iustin Pop
        data inuse is a boolean showing the in-use status of the disk,
406 454723b5 Iustin Pop
        computed as the possibility of re-reading the partition table
407 454723b5 Iustin Pop
        (the meaning of the operation varies with the kernel version,
408 454723b5 Iustin Pop
        but is usually accurate; a mounted disk/partition or swap-area
409 454723b5 Iustin Pop
        or PV with active LVs on it is busy)
410 a8083063 Iustin Pop
411 454723b5 Iustin Pop
  """
412 a8083063 Iustin Pop
  dlist = []
413 a8083063 Iustin Pop
  for name in os.listdir("/sys/block"):
414 577d45d4 Iustin Pop
    if not compat.any([name.startswith(pfx) for pfx in SUPPORTED_TYPES]):
415 a8083063 Iustin Pop
      continue
416 a8083063 Iustin Pop
417 a8083063 Iustin Pop
    size = ReadSize("/sys/block/%s" % name)
418 a8083063 Iustin Pop
419 a8083063 Iustin Pop
    f = open("/sys/block/%s/removable" % name)
420 a8083063 Iustin Pop
    removable = int(f.read().strip())
421 a8083063 Iustin Pop
    f.close()
422 a8083063 Iustin Pop
423 d1687c6f Iustin Pop
    if removable and not opts.removable_ok:
424 a8083063 Iustin Pop
      continue
425 a8083063 Iustin Pop
426 a8083063 Iustin Pop
    dev = ReadDev("/sys/block/%s" % name)
427 a8083063 Iustin Pop
    CheckSysDev(name, dev)
428 a8083063 Iustin Pop
    inuse = not CheckReread(name)
429 a8083063 Iustin Pop
    # Enumerate partitions of the block device
430 a8083063 Iustin Pop
    partitions = []
431 a8083063 Iustin Pop
    for partname in os.listdir("/sys/block/%s" % name):
432 a8083063 Iustin Pop
      if not partname.startswith(name):
433 a8083063 Iustin Pop
        continue
434 a8083063 Iustin Pop
      partdev = ReadDev("/sys/block/%s/%s" % (name, partname))
435 a8083063 Iustin Pop
      partsize = ReadSize("/sys/block/%s/%s" % (name, partname))
436 a8083063 Iustin Pop
      CheckSysDev(partname, partdev)
437 a8083063 Iustin Pop
      partitions.append((partname, partsize, partdev))
438 a8083063 Iustin Pop
    partitions.sort()
439 a8083063 Iustin Pop
    dlist.append((name, size, dev, partitions, inuse))
440 a8083063 Iustin Pop
  dlist.sort()
441 a8083063 Iustin Pop
  return dlist
442 a8083063 Iustin Pop
443 a8083063 Iustin Pop
444 a8083063 Iustin Pop
def GetMountInfo():
445 a8083063 Iustin Pop
  """Reads /proc/mounts and computes the mountpoint-devnum mapping.
446 a8083063 Iustin Pop
447 a8083063 Iustin Pop
  This function reads /proc/mounts, finds the mounted filesystems
448 a8083063 Iustin Pop
  (excepting a hard-coded blacklist of network and virtual
449 a8083063 Iustin Pop
  filesystems) and does a stat on these mountpoints. The st_dev number
450 a8083063 Iustin Pop
  of the results is memorised for later matching against the
451 a8083063 Iustin Pop
  /sys/block devices.
452 a8083063 Iustin Pop
453 454723b5 Iustin Pop
  @rtype: dict
454 454723b5 Iustin Pop
  @return: a {mountpoint: device number} dictionary
455 a8083063 Iustin Pop
456 454723b5 Iustin Pop
  """
457 3374afa9 Guido Trotter
  mountlines = ReadFile("/proc/mounts").splitlines()
458 a8083063 Iustin Pop
  mounts = {}
459 a8083063 Iustin Pop
  for line in mountlines:
460 f4ad2ef0 Iustin Pop
    _, mountpoint, fstype, _ = line.split(None, 3)
461 a8083063 Iustin Pop
    # fs type blacklist
462 a8083063 Iustin Pop
    if fstype in ["nfs", "nfs4", "autofs", "tmpfs", "proc", "sysfs"]:
463 a8083063 Iustin Pop
      continue
464 a8083063 Iustin Pop
    try:
465 a8083063 Iustin Pop
      dev = os.stat(mountpoint).st_dev
466 a8083063 Iustin Pop
    except OSError, err:
467 a8083063 Iustin Pop
      # this should be a fairly rare error, since we are blacklisting
468 a8083063 Iustin Pop
      # network filesystems; with this in mind, we'll ignore it,
469 a8083063 Iustin Pop
      # since the rereadpt check catches in-use filesystems,
470 a8083063 Iustin Pop
      # and this is used for disk information only
471 a8083063 Iustin Pop
      print >> sys.stderr, ("Can't stat mountpoint '%s': %s" %
472 a8083063 Iustin Pop
                            (mountpoint, err))
473 a8083063 Iustin Pop
      print >> sys.stderr, "Ignoring."
474 a8083063 Iustin Pop
      continue
475 a8083063 Iustin Pop
    mounts[dev] = mountpoint
476 a8083063 Iustin Pop
  return mounts
477 a8083063 Iustin Pop
478 a8083063 Iustin Pop
479 a8083063 Iustin Pop
def DevInfo(name, dev, mountinfo):
480 5bbd3f7f Michael Hanselmann
  """Computes miscellaneous information about a block device.
481 a8083063 Iustin Pop
482 454723b5 Iustin Pop
  @type name: string
483 454723b5 Iustin Pop
  @param name: the device name, e.g. sda
484 a8083063 Iustin Pop
485 454723b5 Iustin Pop
  @return: a tuple (mpath, whatvg, fileinfo), where:
486 454723b5 Iustin Pop
      - mpath is the mount path where this device is mounted or None
487 454723b5 Iustin Pop
      - whatvg is the result of the ReadPV function
488 454723b5 Iustin Pop
      - fileinfo is the output of file -bs on the device
489 a8083063 Iustin Pop
490 454723b5 Iustin Pop
  """
491 a8083063 Iustin Pop
  if dev in mountinfo:
492 a8083063 Iustin Pop
    mpath = mountinfo[dev]
493 a8083063 Iustin Pop
  else:
494 a8083063 Iustin Pop
    mpath = None
495 a8083063 Iustin Pop
496 a8083063 Iustin Pop
  whatvg = ReadPV(name)
497 a8083063 Iustin Pop
498 a8083063 Iustin Pop
  result = ExecCommand("file -bs /dev/%s" % name)
499 a8083063 Iustin Pop
  if result.failed:
500 a8083063 Iustin Pop
    fileinfo = "<error: %s>" % result.stderr
501 a8083063 Iustin Pop
  fileinfo = result.stdout[:45]
502 a8083063 Iustin Pop
  return mpath, whatvg, fileinfo
503 a8083063 Iustin Pop
504 a8083063 Iustin Pop
505 d1687c6f Iustin Pop
def ShowDiskInfo(opts):
506 a8083063 Iustin Pop
  """Shows a nicely formatted block device list for this system.
507 a8083063 Iustin Pop
508 5bbd3f7f Michael Hanselmann
  This function shows the user a table with the information gathered
509 a8083063 Iustin Pop
  by the other functions defined, in order to help the user make a
510 a8083063 Iustin Pop
  choice about which disks should be allocated to our volume group.
511 a8083063 Iustin Pop
512 a8083063 Iustin Pop
  """
513 a8083063 Iustin Pop
  mounts = GetMountInfo()
514 d1687c6f Iustin Pop
  dlist = GetDiskList(opts)
515 a8083063 Iustin Pop
516 a8083063 Iustin Pop
  print "------- Disk information -------"
517 e194129a Stephen Shirley
  headers = {
518 e194129a Stephen Shirley
      "name": "Name",
519 e194129a Stephen Shirley
      "size": "Size[M]",
520 e194129a Stephen Shirley
      "used": "Used",
521 e194129a Stephen Shirley
      "mount": "Mount",
522 e194129a Stephen Shirley
      "lvm": "LVM?",
523 e194129a Stephen Shirley
      "info": "Info"
524 e194129a Stephen Shirley
      }
525 e194129a Stephen Shirley
  fields = ["name", "size", "used", "mount", "lvm", "info"]
526 a8083063 Iustin Pop
527 a8083063 Iustin Pop
  flatlist = []
528 a8083063 Iustin Pop
  # Flatten the [(disk, [partition,...]), ...] list
529 a8083063 Iustin Pop
  for name, size, dev, parts, inuse in dlist:
530 a8083063 Iustin Pop
    if inuse:
531 a8083063 Iustin Pop
      str_inuse = "yes"
532 a8083063 Iustin Pop
    else:
533 a8083063 Iustin Pop
      str_inuse = "no"
534 a8083063 Iustin Pop
    flatlist.append((name, size, dev, str_inuse))
535 a8083063 Iustin Pop
    for partname, partsize, partdev in parts:
536 a8083063 Iustin Pop
      flatlist.append((partname, partsize, partdev, ""))
537 a8083063 Iustin Pop
538 e194129a Stephen Shirley
  strlist = []
539 a8083063 Iustin Pop
  for name, size, dev, in_use in flatlist:
540 a8083063 Iustin Pop
    mp, vgname, fileinfo = DevInfo(name, dev, mounts)
541 a8083063 Iustin Pop
    if mp is None:
542 a8083063 Iustin Pop
      mp = "-"
543 a8083063 Iustin Pop
    if vgname is None:
544 a8083063 Iustin Pop
      lvminfo = "-"
545 a8083063 Iustin Pop
    elif vgname == "":
546 a8083063 Iustin Pop
      lvminfo = "yes,free"
547 a8083063 Iustin Pop
    else:
548 a8083063 Iustin Pop
      lvminfo = "in %s" % vgname
549 a8083063 Iustin Pop
550 a8083063 Iustin Pop
    if len(name) > 3:
551 a8083063 Iustin Pop
      # Indent partitions
552 a8083063 Iustin Pop
      name = " %s" % name
553 e194129a Stephen Shirley
554 e194129a Stephen Shirley
    strlist.append([name, "%.2f" % (float(size) / 1024 / 1024),
555 e194129a Stephen Shirley
                    in_use, mp, lvminfo, fileinfo])
556 e194129a Stephen Shirley
557 e194129a Stephen Shirley
  data = cli.GenerateTable(headers, fields, None,
558 e194129a Stephen Shirley
                           strlist, numfields=["size"])
559 e194129a Stephen Shirley
560 e194129a Stephen Shirley
  for line in data:
561 e194129a Stephen Shirley
    print line
562 a8083063 Iustin Pop
563 a8083063 Iustin Pop
564 a8083063 Iustin Pop
def CheckReread(name):
565 a8083063 Iustin Pop
  """Check to see if a block device is in use.
566 a8083063 Iustin Pop
567 577d45d4 Iustin Pop
  Uses blockdev to reread the partition table of a block device (or
568 577d45d4 Iustin Pop
  fuser if the device is not partitionable), and thus compute the
569 577d45d4 Iustin Pop
  in-use status.  See the discussion in GetDiskList about the meaning
570 577d45d4 Iustin Pop
  of 'in use'.
571 a8083063 Iustin Pop
572 454723b5 Iustin Pop
  @rtype: boolean
573 454723b5 Iustin Pop
  @return: the in-use status of the device
574 a8083063 Iustin Pop
575 454723b5 Iustin Pop
  """
576 577d45d4 Iustin Pop
  use_blockdev = IsPartitioned(name)
577 577d45d4 Iustin Pop
  if use_blockdev:
578 577d45d4 Iustin Pop
    cmd = "blockdev --rereadpt /dev/%s" % name
579 577d45d4 Iustin Pop
  else:
580 577d45d4 Iustin Pop
    cmd = "fuser -vam /dev/%s" % name
581 577d45d4 Iustin Pop
582 f4ad2ef0 Iustin Pop
  for _ in range(3):
583 577d45d4 Iustin Pop
    result = ExecCommand(cmd)
584 577d45d4 Iustin Pop
    if not use_blockdev and result.failed:
585 577d45d4 Iustin Pop
      break
586 577d45d4 Iustin Pop
    elif not result.failed:
587 a8083063 Iustin Pop
      break
588 a8083063 Iustin Pop
    time.sleep(2)
589 a8083063 Iustin Pop
590 577d45d4 Iustin Pop
  if use_blockdev:
591 577d45d4 Iustin Pop
    return not result.failed
592 577d45d4 Iustin Pop
  else:
593 577d45d4 Iustin Pop
    return result.failed
594 a8083063 Iustin Pop
595 a8083063 Iustin Pop
596 a8083063 Iustin Pop
def WipeDisk(name):
597 a8083063 Iustin Pop
  """Wipes a block device.
598 a8083063 Iustin Pop
599 a8083063 Iustin Pop
  This function wipes a block device, by clearing and re-reading the
600 a8083063 Iustin Pop
  partition table. If not successful, it writes back the old partition
601 a8083063 Iustin Pop
  data, and leaves the cleanup to the user.
602 a8083063 Iustin Pop
603 454723b5 Iustin Pop
  @param name: the device name (e.g. sda)
604 454723b5 Iustin Pop
605 a8083063 Iustin Pop
  """
606 a8083063 Iustin Pop
607 a8083063 Iustin Pop
  if not CheckReread(name):
608 f4bc1f2c Michael Hanselmann
    raise OperationalError("CRITICAL: disk %s you selected seems to be in"
609 f4bc1f2c Michael Hanselmann
                           " use. ABORTING!" % name)
610 a8083063 Iustin Pop
611 a8083063 Iustin Pop
  fd = os.open("/dev/%s" % name, os.O_RDWR | os.O_SYNC)
612 a8083063 Iustin Pop
  olddata = os.read(fd, 512)
613 a8083063 Iustin Pop
  if len(olddata) != 512:
614 f4bc1f2c Michael Hanselmann
    raise OperationalError("CRITICAL: Can't read partition table information"
615 f4bc1f2c Michael Hanselmann
                           " from /dev/%s (needed 512 bytes, got %d" %
616 a8083063 Iustin Pop
                           (name, len(olddata)))
617 a8083063 Iustin Pop
  newdata = "\0" * 512
618 a8083063 Iustin Pop
  os.lseek(fd, 0, 0)
619 a8083063 Iustin Pop
  bytes_written = os.write(fd, newdata)
620 a8083063 Iustin Pop
  os.close(fd)
621 a8083063 Iustin Pop
  if bytes_written != 512:
622 a8083063 Iustin Pop
    raise OperationalError("CRITICAL: Can't write partition table information"
623 f4bc1f2c Michael Hanselmann
                           " to /dev/%s (tried to write 512 bytes, written"
624 f4bc1f2c Michael Hanselmann
                           " %d. I don't know how to cleanup. Sorry." %
625 a8083063 Iustin Pop
                           (name, bytes_written))
626 a8083063 Iustin Pop
627 a8083063 Iustin Pop
  if not CheckReread(name):
628 a8083063 Iustin Pop
    fd = os.open("/dev/%s" % name, os.O_RDWR | os.O_SYNC)
629 a8083063 Iustin Pop
    os.write(fd, olddata)
630 a8083063 Iustin Pop
    os.close(fd)
631 f4bc1f2c Michael Hanselmann
    raise OperationalError("CRITICAL: disk %s which I have just wiped cannot"
632 f4bc1f2c Michael Hanselmann
                           " reread partition table. Most likely, it is"
633 f4bc1f2c Michael Hanselmann
                           " in use. You have to clean after this yourself."
634 f4bc1f2c Michael Hanselmann
                           " I tried to restore the old partition table,"
635 f4bc1f2c Michael Hanselmann
                           " but I cannot guarantee nothing has broken." %
636 a8083063 Iustin Pop
                           name)
637 a8083063 Iustin Pop
638 a8083063 Iustin Pop
639 a8083063 Iustin Pop
def PartitionDisk(name):
640 a8083063 Iustin Pop
  """Partitions a disk.
641 a8083063 Iustin Pop
642 a8083063 Iustin Pop
  This function creates a single partition spanning the entire disk,
643 a8083063 Iustin Pop
  by means of fdisk.
644 a8083063 Iustin Pop
645 454723b5 Iustin Pop
  @param name: the device name, e.g. sda
646 454723b5 Iustin Pop
647 a8083063 Iustin Pop
  """
648 a8083063 Iustin Pop
  result = ExecCommand(
649 a8083063 Iustin Pop
    'echo ,,8e, | sfdisk /dev/%s' % name)
650 a8083063 Iustin Pop
  if result.failed:
651 f4bc1f2c Michael Hanselmann
    raise OperationalError("CRITICAL: disk %s which I have just partitioned"
652 f4bc1f2c Michael Hanselmann
                           " cannot reread its partition table, or there"
653 f4bc1f2c Michael Hanselmann
                           " is some other sfdisk error. Likely, it is in"
654 f4bc1f2c Michael Hanselmann
                           " use. You have to clean this yourself. Error"
655 f4bc1f2c Michael Hanselmann
                           " message from sfdisk: %s" %
656 a8083063 Iustin Pop
                           (name, result.output))
657 a8083063 Iustin Pop
658 a8083063 Iustin Pop
659 a8083063 Iustin Pop
def CreatePVOnDisk(name):
660 a8083063 Iustin Pop
  """Creates a physical volume on a block device.
661 a8083063 Iustin Pop
662 a8083063 Iustin Pop
  This function creates a physical volume on a block device, overriding
663 a8083063 Iustin Pop
  all warnings. So it can wipe existing PVs and PVs which are in a VG.
664 a8083063 Iustin Pop
665 454723b5 Iustin Pop
  @param name: the device name, e.g. sda
666 a8083063 Iustin Pop
667 a8083063 Iustin Pop
  """
668 577d45d4 Iustin Pop
  device = DeviceName(name)
669 577d45d4 Iustin Pop
  result = ExecCommand("pvcreate -yff %s" % device)
670 a8083063 Iustin Pop
  if result.failed:
671 f4bc1f2c Michael Hanselmann
    raise OperationalError("I cannot create a physical volume on"
672 577d45d4 Iustin Pop
                           " %s. Error message: %s."
673 f4bc1f2c Michael Hanselmann
                           " Please clean up yourself." %
674 577d45d4 Iustin Pop
                           (device, result.output))
675 a8083063 Iustin Pop
676 a8083063 Iustin Pop
677 a8083063 Iustin Pop
def CreateVG(vgname, disks):
678 a8083063 Iustin Pop
  """Creates the volume group.
679 a8083063 Iustin Pop
680 a8083063 Iustin Pop
  This function creates a volume group named `vgname` on the disks
681 a8083063 Iustin Pop
  given as parameters. The physical extent size is set to 64MB.
682 a8083063 Iustin Pop
683 454723b5 Iustin Pop
  @param disks: a list of disk names, e.g. ['sda','sdb']
684 a8083063 Iustin Pop
685 a8083063 Iustin Pop
  """
686 577d45d4 Iustin Pop
  pnames = [DeviceName(d) for d in disks]
687 a8083063 Iustin Pop
  result = ExecCommand("vgcreate -s 64MB '%s' %s" % (vgname, " ".join(pnames)))
688 a8083063 Iustin Pop
  if result.failed:
689 f4bc1f2c Michael Hanselmann
    raise OperationalError("I cannot create the volume group %s from"
690 f4bc1f2c Michael Hanselmann
                           " disks %s. Error message: %s. Please clean up"
691 f4bc1f2c Michael Hanselmann
                           " yourself." %
692 a8083063 Iustin Pop
                           (vgname, " ".join(disks), result.output))
693 a8083063 Iustin Pop
694 a8083063 Iustin Pop
695 a8083063 Iustin Pop
def ValidateDiskList(options):
696 a8083063 Iustin Pop
  """Validates or computes the disk list for create.
697 a8083063 Iustin Pop
698 a8083063 Iustin Pop
  This function either computes the available disk list (if the user
699 a8083063 Iustin Pop
  gave --alldisks option), or validates the user-given disk list (by
700 a8083063 Iustin Pop
  using the --disks option) such that all given disks are present and
701 a8083063 Iustin Pop
  not in use.
702 a8083063 Iustin Pop
703 454723b5 Iustin Pop
  @param options: the options returned from OptParser.parse_options
704 a8083063 Iustin Pop
705 454723b5 Iustin Pop
  @return: a list of disk names, e.g. ['sda', 'sdb']
706 a8083063 Iustin Pop
707 454723b5 Iustin Pop
  """
708 d1687c6f Iustin Pop
  sysdisks = GetDiskList(options)
709 a8083063 Iustin Pop
  if not sysdisks:
710 f4bc1f2c Michael Hanselmann
    raise PrereqError("no disks found (I looked for"
711 f4bc1f2c Michael Hanselmann
                      " non-removable block devices).")
712 a8083063 Iustin Pop
  sysd_free = []
713 a8083063 Iustin Pop
  sysd_used = []
714 f4ad2ef0 Iustin Pop
  for name, _, _, _, used in sysdisks:
715 a8083063 Iustin Pop
    if used:
716 a8083063 Iustin Pop
      sysd_used.append(name)
717 a8083063 Iustin Pop
    else:
718 a8083063 Iustin Pop
      sysd_free.append(name)
719 a8083063 Iustin Pop
720 a8083063 Iustin Pop
  if not sysd_free:
721 a8083063 Iustin Pop
    raise PrereqError("no free disks found! (%d in-use disks)" %
722 a8083063 Iustin Pop
                      len(sysd_used))
723 a8083063 Iustin Pop
  if options.alldisks:
724 a8083063 Iustin Pop
    disklist = sysd_free
725 a8083063 Iustin Pop
  elif options.disks:
726 a8083063 Iustin Pop
    disklist = options.disks.split(",")
727 a8083063 Iustin Pop
    for name in disklist:
728 a8083063 Iustin Pop
      if name in sysd_used:
729 a8083063 Iustin Pop
        raise ParameterError("disk %s is in use, cannot wipe!" % name)
730 a8083063 Iustin Pop
      if name not in sysd_free:
731 a8083063 Iustin Pop
        raise ParameterError("cannot find disk %s!" % name)
732 a8083063 Iustin Pop
  else:
733 a8083063 Iustin Pop
    raise ParameterError("Please use either --alldisks or --disks!")
734 a8083063 Iustin Pop
735 a8083063 Iustin Pop
  return disklist
736 a8083063 Iustin Pop
737 f4bc1f2c Michael Hanselmann
738 a8083063 Iustin Pop
def BootStrap():
739 454723b5 Iustin Pop
  """Actual main routine.
740 a8083063 Iustin Pop
741 454723b5 Iustin Pop
  """
742 a8083063 Iustin Pop
  CheckPrereq()
743 a8083063 Iustin Pop
744 a8083063 Iustin Pop
  options, args = ParseOptions()
745 a8083063 Iustin Pop
  vgname = options.vgname
746 a8083063 Iustin Pop
  command = args.pop(0)
747 a8083063 Iustin Pop
  if command == "diskinfo":
748 d1687c6f Iustin Pop
    ShowDiskInfo(options)
749 a8083063 Iustin Pop
    return
750 a8083063 Iustin Pop
  if command != "create":
751 a8083063 Iustin Pop
    Usage()
752 a8083063 Iustin Pop
753 a8083063 Iustin Pop
  exists, lv_count, vg_size, vg_free = CheckVGExists(vgname)
754 a8083063 Iustin Pop
  if exists:
755 a8083063 Iustin Pop
    raise PrereqError("It seems volume group '%s' already exists:\n"
756 a8083063 Iustin Pop
                      "  LV count: %s, size: %s, free: %s." %
757 a8083063 Iustin Pop
                      (vgname, lv_count, vg_size, vg_free))
758 a8083063 Iustin Pop
759 a8083063 Iustin Pop
760 a8083063 Iustin Pop
  disklist = ValidateDiskList(options)
761 a8083063 Iustin Pop
762 a8083063 Iustin Pop
  for disk in disklist:
763 a8083063 Iustin Pop
    WipeDisk(disk)
764 577d45d4 Iustin Pop
    if IsPartitioned(disk):
765 577d45d4 Iustin Pop
      PartitionDisk(disk)
766 a8083063 Iustin Pop
  for disk in disklist:
767 a8083063 Iustin Pop
    CreatePVOnDisk(disk)
768 a8083063 Iustin Pop
  CreateVG(vgname, disklist)
769 a8083063 Iustin Pop
770 f4ad2ef0 Iustin Pop
  status, lv_count, size, _ = CheckVGExists(vgname)
771 a8083063 Iustin Pop
  if status:
772 a8083063 Iustin Pop
    print "Done! %s: size %s GiB, disks: %s" % (vgname, size,
773 f4bc1f2c Michael Hanselmann
                                              ",".join(disklist))
774 a8083063 Iustin Pop
  else:
775 f4bc1f2c Michael Hanselmann
    raise OperationalError("Although everything seemed ok, the volume"
776 f4bc1f2c Michael Hanselmann
                           " group did not get created.")
777 a8083063 Iustin Pop
778 a8083063 Iustin Pop
779 a8083063 Iustin Pop
def main():
780 454723b5 Iustin Pop
  """Application entry point.
781 a8083063 Iustin Pop
782 a8083063 Iustin Pop
  This is just a wrapper over BootStrap, to handle our own exceptions.
783 a8083063 Iustin Pop
784 454723b5 Iustin Pop
  """
785 a8083063 Iustin Pop
  try:
786 a8083063 Iustin Pop
    BootStrap()
787 a8083063 Iustin Pop
  except PrereqError, err:
788 a8083063 Iustin Pop
    print >> sys.stderr, "The prerequisites for running this tool are not met."
789 f4bc1f2c Michael Hanselmann
    print >> sys.stderr, ("Please make sure you followed all the steps in"
790 f4bc1f2c Michael Hanselmann
                          " the build document.")
791 a8083063 Iustin Pop
    print >> sys.stderr, "Description: %s" % str(err)
792 a8083063 Iustin Pop
    sys.exit(1)
793 a8083063 Iustin Pop
  except SysconfigError, err:
794 f4bc1f2c Michael Hanselmann
    print >> sys.stderr, ("This system's configuration seems wrong, at"
795 f4bc1f2c Michael Hanselmann
                          " least is not what I expect.")
796 f4bc1f2c Michael Hanselmann
    print >> sys.stderr, ("Please check that the installation didn't fail"
797 f4bc1f2c Michael Hanselmann
                          " at some step.")
798 a8083063 Iustin Pop
    print >> sys.stderr, "Description: %s" % str(err)
799 a8083063 Iustin Pop
    sys.exit(1)
800 a8083063 Iustin Pop
  except ParameterError, err:
801 f4bc1f2c Michael Hanselmann
    print >> sys.stderr, ("Some parameters you gave to the program or the"
802 f4bc1f2c Michael Hanselmann
                          " invocation is wrong. ")
803 a8083063 Iustin Pop
    print >> sys.stderr, "Description: %s" % str(err)
804 a8083063 Iustin Pop
    Usage()
805 a8083063 Iustin Pop
  except OperationalError, err:
806 f4bc1f2c Michael Hanselmann
    print >> sys.stderr, ("A serious error has happened while modifying"
807 f4bc1f2c Michael Hanselmann
                          " the system's configuration.")
808 f4bc1f2c Michael Hanselmann
    print >> sys.stderr, ("Please review the error message below and make"
809 f4bc1f2c Michael Hanselmann
                          " sure you clean up yourself.")
810 f4bc1f2c Michael Hanselmann
    print >> sys.stderr, ("It is most likely that the system configuration"
811 f4bc1f2c Michael Hanselmann
                          " has been partially altered.")
812 a8083063 Iustin Pop
    print >> sys.stderr, str(err)
813 a8083063 Iustin Pop
    sys.exit(1)
814 a8083063 Iustin Pop
  except ProgrammingError, err:
815 f4bc1f2c Michael Hanselmann
    print >> sys.stderr, ("Internal application error. Please signal this"
816 f4bc1f2c Michael Hanselmann
                          " to xencluster-team.")
817 a8083063 Iustin Pop
    print >> sys.stderr, "Error description: %s" % str(err)
818 a8083063 Iustin Pop
    sys.exit(1)
819 a8083063 Iustin Pop
  except Error, err:
820 a8083063 Iustin Pop
    print >> sys.stderr, "Unhandled application error: %s" % err
821 a8083063 Iustin Pop
    sys.exit(1)
822 a8083063 Iustin Pop
  except (IOError, OSError), err:
823 a8083063 Iustin Pop
    print >> sys.stderr, "I/O error detected, please report."
824 a8083063 Iustin Pop
    print >> sys.stderr, "Description: %s" % str(err)
825 a8083063 Iustin Pop
    sys.exit(1)
826 a8083063 Iustin Pop
827 a8083063 Iustin Pop
828 a8083063 Iustin Pop
if __name__ == "__main__":
829 a8083063 Iustin Pop
  main()