source: trunk/packages/sipb-xen-guest-installer/sipb-xen-guest-installer/files/usr/sbin/sipb-xen-duplicate @ 231

Last change on this file since 231 was 231, checked in by price, 16 years ago

prototype fast installer.

To install a distribution on a new volume, we take an existing
installed volume produced with sipb-xen-make-iso, and

  1. copy GRUB's data with dd
  2. frob the partition table with sfdisk, if the disk size is different
  3. make the filesystem
  4. twiddle the hostname and root password and whatever else
  5. make the swap area
  6. boot!

In this prototype, steps 2 and 4 aren't implemented yet;
steps 1, 3, and 5 all use numbers that come from what the
sipb-xen-make-iso etch installer does rather than from
actually reading the partition table; and the whole thing
is just a program in /usr/sbin, not integrated into what
remctl / the web app invoke.

It all takes about thirty seconds (28.0s most recently),
excluding the boot.

  • Property svn:executable set to *
File size: 2.8 KB
Line 
1#!/usr/bin/env python
2
3import sys
4import os
5import shutil
6import tempfile
7from subprocess import call, Popen
8
9# TODO:
10# . pick a loop device sanely
11# - adapt size of partition to fit volume
12# - fix hostname, root password
13# - (once debugging diminishes) umount, losetup -d, maybe rm -r
14# - avoid race conditions with other loop-device users, too (somehow)
15# - get numbers from actual source partition table rather than
16#   as magic numbers based on what sipb-xen-make-iso does with etch.
17
18def losetup(source, offset=0):
19  # XXX we avoid colliding with other instances of ourself,
20  #     but when it comes to other loop-device users we just
21  #     pick a range things don't seem to use and hope...
22  lockfilename = '/tmp/losetup.lock'
23  os.close(os.open(lockfilename, os.O_CREAT+os.O_EXCL)) #lock
24  try:
25    loopdevice = None
26    for i in xrange(32,60): # totally arbitrary, just looks to be unused on black-mesa
27      filename = '/dev/loop%d'%i
28      if 0 == len(file(filename).read(1)):
29        loopdevice = filename # it's empty
30        break
31    if loopdevice is not None:
32      call(['losetup', '-o', str(offset), loopdevice, source])
33  finally:
34    os.unlink(lockfilename) #unlock
35  return loopdevice
36  # XX this means we can duplicate 9 at once.  since it takes around 30 seconds,
37  # this seems like an adequate capacity.
38
39def duplicate_lv(source, dest):
40  '''duplicate boot record, filesystem from LV source to LV dest
41 
42  source, dest should be device filenames.
43  '''
44  # XXX this is very specific to what the etch sipb-xen-make-iso installer does.
45  # XXXX also, it's specific to four gigs.
46  # step 1: copy the MBR
47  call(['dd', 'if='+source, 'bs=512', 'count=63', 'of='+dest])
48  # step 2: fix up partition table
49  # XX actually do this; this is our opportunity to resize the filesystem
50  # step 3: make the filesystem, and copy its contents in
51  sourcefs = losetup(source, 32256)
52  destfs = losetup(dest, 32256)
53  call(['mkfs.ext3', '-b', '4096', destfs, '987989'])
54  tmptree = tempfile.mkdtemp('', 'auto-install.dup.', '/tmp')
55  os.mkdir(tmptree+"/source")
56  call(['mount', '-t', 'ext3', '-o', 'ro', sourcefs, tmptree+"/source"])
57  os.mkdir(tmptree+"/dest")
58  call(['mount', '-t', 'ext3', destfs, tmptree+"/dest"])
59  call(['cp', '-aT', tmptree+"/source", tmptree+"/dest"])
60  # step 4: twiddle what we want to twiddle
61  # XX do this
62  # step 5: make the swap area
63  swapfs = losetup(dest, 4046870016)
64  call(['mkswap', swapfs, str(240943)])
65  # call(['losetup', '-d', swapfs])
66  print 'losetup -d '+swapfs
67  # step 6: clean up.
68  # XX actually unmount etc (leaving it is for debugging)
69  print 'umount '+tmptree+'/source'
70  call(['umount', tmptree+"/dest"]) # needed to flush writes
71  print 'losetup -d '+sourcefs
72  print 'losetup -d '+destfs
73
74if __name__ == '__main__':
75  duplicate_lv(*sys.argv[1:])
Note: See TracBrowser for help on using the repository browser.