Prototype fast installer using a special guest.
authorGreg Price <price@mit.edu>
Tue, 13 Nov 2007 10:10:10 +0000 (05:10 -0500)
committerGreg Price <price@mit.edu>
Tue, 13 Nov 2007 10:10:10 +0000 (05:10 -0500)
Rather than poke directly in the boot sector, partition table,
etc, which caused so much pain last week (r231), we just dd
the entire disk.  Then we poke at the bits that need to change
(like secrets, the hostname, the root password, the filesystem uuids).
Since this poking is distribution-dependent, we want it to be
supplied by the image, so to make that safe we run it in a VM.

The plan is
 1. source image is dd'd (in the host) to the target image
 2. special copying-installer image is booted, with access to target
    and to a small image containing its arguments
 3. copying-installer guest reads arguments, mounts target,
    runs a script with a well-known name in target, passing arguments.

Bits I haven't done yet include
 - frob grub config in the copying-installer image so it boots
   with init = the copying-installer script (doing this manually for testing)
 - install script into copying-installer, or into my example image,
   in a sane automated way (they're checked into partial/ here)
 - all the tasks the image's script ought to actually carry out
 - make this all available from remctl and the web pages.

svn path=/trunk/packages/sipb-xen-guest-installer/sipb-xen-guest-installer/; revision=245

files/usr/sbin/sipb-xen-duplicate
partial/copying-installer.sh [new file with mode: 0644]
partial/post-copy [new file with mode: 0644]

index fa24e23..a78d3a1 100755 (executable)
@@ -1,10 +1,10 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2.5
 
 import sys
 import os
 import shutil
 import tempfile
 
 import sys
 import os
 import shutil
 import tempfile
-from subprocess import call, Popen
+from subprocess import call, check_call, Popen
 
 # TODO:
 # . pick a loop device sanely
 
 # TODO:
 # . pick a loop device sanely
@@ -71,5 +71,30 @@ def duplicate_lv(source, dest):
   print 'losetup -d '+sourcefs
   print 'losetup -d '+destfs
 
   print 'losetup -d '+sourcefs
   print 'losetup -d '+destfs
 
+def duplicate_by_vm(source, target, *args):
+  # source, target should be machine names
+  prefix = 'd_'
+  # 1. copy (by dd) source to target
+  source_device = '/dev/xenvg/' + prefix + source + '_hda'
+  target_device = '/dev/xenvg/' + prefix + target + '_hda'
+  #check_call(['/bin/dd', 'bs=1M', 'conv=nocreat',
+  #            'if='+source_device, 'of='+target_device])
+  # 2. prepare arguments volume
+  args_volume = prefix+target+'_args'
+  args_device = '/dev/xenvg/' + args_volume
+  check_call(['/sbin/lvcreate', 'xenvg', '--name', args_volume, '--size', '4K'])
+  file(args_device, 'w').write('\n'.join(args) + '\n')
+
+  copier_device = '/dev/xenvg/d_wert_hda'
+  check_call(['/usr/sbin/xm', 'create', 'sipb-database',
+              'machine_name='+target,
+              'disks=' + ' '.join(['phy:'+copier_device+',hda,w',
+                                   'phy:'+target_device+',hdc,w',
+                                   'phy:'+args_device+',hdd,w'])])
+  boot = 'c'
+
+  # XXX make this happen! check_call(['/sbin/lvremove', '-f', 'xenvg/'+args_volume])
+  
+
 if __name__ == '__main__':
 if __name__ == '__main__':
-  duplicate_lv(*sys.argv[1:])
+  duplicate_by_vm(*sys.argv[1:])
diff --git a/partial/copying-installer.sh b/partial/copying-installer.sh
new file mode 100644 (file)
index 0000000..79678a2
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+# hda is the copying-installer image itself
+# hdb is unused (was the source image)
+# hdc is the target image
+# hdd is the arguments image
+
+exec 3</dev/hdd
+read -r -u 3 HOSTNAME
+read -r -u 3 ROOTPW
+exec 3<&-
+
+mount /dev/hdc1 /mnt/new
+/mnt/new/post-copy /mnt/new "$HOSTNAME" "$ROOTPW"
+umount /mnt/new
+sync
diff --git a/partial/post-copy b/partial/post-copy
new file mode 100644 (file)
index 0000000..46552ad
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/bash
+TARGET="$1"
+HOSTNAME="$2"
+ROOTPW="$3"
+(printf "%s\n" "$ROOTPW"; sleep .2; printf "%s\n" "$ROOTPW") \
+ | /usr/sbin/chroot "$TARGET" /usr/bin/passwd root