Statistics
| Branch: | Tag: | Revision:

root / tools / lvmstrap @ c118d1f4

History | View | Annotate | Download (23.9 kB)

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