From: Greg Price Date: Sun, 30 Mar 2008 06:49:43 +0000 (-0400) Subject: copying installer works now (maybe?) X-Git-Tag: sipb-xen-guest-installer/1.0~4 X-Git-Url: http://xvm.mit.edu/gitweb/invirt/packages/invirt-autoinstaller.git/commitdiff_plain/aa65697475962c7fc256af063bcd5729e7b649b7 copying installer works now (maybe?) At least for the image 'ice3', which IIRC was created with /usr/sbin/sipb-xen-make-iso. It's an etch amd64 image. It also had to have package nullmailer installed, replacing exim4. svn path=/trunk/packages/sipb-xen-guest-installer/; revision=336 --- diff --git a/files/usr/sbin/sipb-xen-duplicate b/files/usr/sbin/sipb-xen-duplicate index a78d3a1..a01bf80 100755 --- a/files/usr/sbin/sipb-xen-duplicate +++ b/files/usr/sbin/sipb-xen-duplicate @@ -4,12 +4,13 @@ import sys import os import shutil import tempfile -from subprocess import call, check_call, Popen +import time +from subprocess import call, check_call, Popen, PIPE # TODO: # . pick a loop device sanely -# - adapt size of partition to fit volume -# - fix hostname, root password +# x adapt size of partition to fit volume +# . fix hostname, root password # - (once debugging diminishes) umount, losetup -d, maybe rm -r # - avoid race conditions with other loop-device users, too (somehow) # - get numbers from actual source partition table rather than @@ -30,6 +31,8 @@ def losetup(source, offset=0): break if loopdevice is not None: call(['losetup', '-o', str(offset), loopdevice, source]) + else: + raise RuntimeError('out of loop devices for copying VM image: too many at once?') finally: os.unlink(lockfilename) #unlock return loopdevice @@ -37,9 +40,12 @@ def losetup(source, offset=0): # this seems like an adequate capacity. def duplicate_lv(source, dest): - '''duplicate boot record, filesystem from LV source to LV dest + '''OBSOLETE: duplicate boot record, filesystem from LV source to LV dest source, dest should be device filenames. + + Now we just dd. Doesn't support resizing, but it's easier, + especially if we allow the partition table to vary between images. ''' # XXX this is very specific to what the etch sipb-xen-make-iso installer does. # XXXX also, it's specific to four gigs. @@ -51,7 +57,7 @@ def duplicate_lv(source, dest): sourcefs = losetup(source, 32256) destfs = losetup(dest, 32256) call(['mkfs.ext3', '-b', '4096', destfs, '987989']) - tmptree = tempfile.mkdtemp('', 'auto-install.dup.', '/tmp') + tmptree = tempfile.mkdtemp('', 'auto-install.dup.', '/tmp')#yes, args backward os.mkdir(tmptree+"/source") call(['mount', '-t', 'ext3', '-o', 'ro', sourcefs, tmptree+"/source"]) os.mkdir(tmptree+"/dest") @@ -71,30 +77,68 @@ def duplicate_lv(source, dest): 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 +def frob_copy(target, *args): + # 1. 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') + # 2. invoke frobber vm 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]) - + # XXX should check_call(['/sbin/lvremove', '-f', 'xenvg/'+args_volume]) + +def frob_copy_simple(target, hostname, rootpw, *args): + """target should be an LV device filename + + This is highly specific to the etch install produced by sipb-xen-make-iso. + Generalizing and customizing to other distros is left to the future... + """ + # 1: mount filesystem + fs = losetup(target, 32256) + mntdir = tempfile.mkdtemp('', 'auto-install.frob.', '/tmp') + call(['mount', '-t', 'ext3', fs, mntdir]) + # 2: do frobbing + # 2a: (printf "%s\n" "$ROOTPW"; sleep .3; printf "%s\n" "$ROOTPW") + # | /usr/sbin/chroot "$TARGET" /usr/bin/passwd root + p = Popen(['/usr/sbin/chroot', mntdir, '/usr/bin/passwd', 'root'], stdin=PIPE) + p.stdin.write(rootpw+'\n') + time.sleep(1) + p.stdin.write(rootpw+'\n') + p.stdin.close() + p.wait() + os.chdir(mntdir) + # 2b: clear generated file that has eth0's old MAC address + # rm $TARGET/etc/udev/rules.d/z25_persistent-net.rules + os.unlink('etc/udev/rules.d/z25_persistent-net.rules') + # 2c: hostname. + # XX Use nullmailer in image, not exim4. (Fewer copies of hostname.) + # 2c1: rm /var/lib/dhcp3/dhclient.eth0.leases + os.unlink('var/lib/dhcp3/dhclient.eth0.leases') + # 2c2: /etc/hosts, /etc/hostname; /etc/motd? /etc/mailname? + call(['perl', '-i', '-pe', 's/ice3.servers.csail.mit.edu/'+hostname+'/g', + 'etc/hosts', 'etc/hostname', 'etc/motd', 'etc/mailname']) + # 3: clean up + os.chdir('/') + call(['umount', mntdir]) + call(['losetup', '-d', fs]) + +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. frob target + frob_copy_simple(target_device, *args) if __name__ == '__main__': duplicate_by_vm(*sys.argv[1:])