Statistics
| Branch: | Tag: | Revision:

root / tools / lvmstrap @ d1687c6f

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