Statistics
| Branch: | Tag: | Revision:

root / tools / lvmstrap @ 454723b5

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