X-Git-Url: http://xvm.mit.edu/gitweb/invirt/packages/invirt-autoinstaller.git/blobdiff_plain/4225e52ef773ad3aea65ea1081ddf6dfc7235a9f..db71340c2668dc8de6a9412bcb526dc4336e8471:/files/usr/sbin/sipb-xen-duplicate?ds=sidebyside diff --git a/files/usr/sbin/sipb-xen-duplicate b/files/usr/sbin/sipb-xen-duplicate new file mode 100755 index 0000000..fa24e23 --- /dev/null +++ b/files/usr/sbin/sipb-xen-duplicate @@ -0,0 +1,75 @@ +#!/usr/bin/env python + +import sys +import os +import shutil +import tempfile +from subprocess import call, Popen + +# TODO: +# . pick a loop device sanely +# - 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 +# as magic numbers based on what sipb-xen-make-iso does with etch. + +def losetup(source, offset=0): + # XXX we avoid colliding with other instances of ourself, + # but when it comes to other loop-device users we just + # pick a range things don't seem to use and hope... + lockfilename = '/tmp/losetup.lock' + os.close(os.open(lockfilename, os.O_CREAT+os.O_EXCL)) #lock + try: + loopdevice = None + for i in xrange(32,60): # totally arbitrary, just looks to be unused on black-mesa + filename = '/dev/loop%d'%i + if 0 == len(file(filename).read(1)): + loopdevice = filename # it's empty + break + if loopdevice is not None: + call(['losetup', '-o', str(offset), loopdevice, source]) + finally: + os.unlink(lockfilename) #unlock + return loopdevice + # XX this means we can duplicate 9 at once. since it takes around 30 seconds, + # this seems like an adequate capacity. + +def duplicate_lv(source, dest): + '''duplicate boot record, filesystem from LV source to LV dest + + source, dest should be device filenames. + ''' + # XXX this is very specific to what the etch sipb-xen-make-iso installer does. + # XXXX also, it's specific to four gigs. + # step 1: copy the MBR + call(['dd', 'if='+source, 'bs=512', 'count=63', 'of='+dest]) + # step 2: fix up partition table + # XX actually do this; this is our opportunity to resize the filesystem + # step 3: make the filesystem, and copy its contents in + sourcefs = losetup(source, 32256) + destfs = losetup(dest, 32256) + call(['mkfs.ext3', '-b', '4096', destfs, '987989']) + tmptree = tempfile.mkdtemp('', 'auto-install.dup.', '/tmp') + os.mkdir(tmptree+"/source") + call(['mount', '-t', 'ext3', '-o', 'ro', sourcefs, tmptree+"/source"]) + os.mkdir(tmptree+"/dest") + call(['mount', '-t', 'ext3', destfs, tmptree+"/dest"]) + call(['cp', '-aT', tmptree+"/source", tmptree+"/dest"]) + # step 4: twiddle what we want to twiddle + # XX do this + # step 5: make the swap area + swapfs = losetup(dest, 4046870016) + call(['mkswap', swapfs, str(240943)]) + # call(['losetup', '-d', swapfs]) + print 'losetup -d '+swapfs + # step 6: clean up. + # XX actually unmount etc (leaving it is for debugging) + print 'umount '+tmptree+'/source' + call(['umount', tmptree+"/dest"]) # needed to flush writes + print 'losetup -d '+sourcefs + print 'losetup -d '+destfs + +if __name__ == '__main__': + duplicate_lv(*sys.argv[1:])