Statistics
| Branch: | Tag: | Revision:

root / tools / lvmstrap @ 8b3fd458

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