1 #!/usr/bin/env python2.5
8 from subprocess import call, check_call, Popen, PIPE
10 def losetup(source, offset=0):
11 # XXX we avoid colliding with other instances of ourself,
12 # but when it comes to other loop-device users we just
13 # pick a range things don't seem to use and hope...
14 lockfilename = '/tmp/losetup.lock'
15 os.close(os.open(lockfilename, os.O_CREAT+os.O_EXCL)) #lock
18 for i in xrange(32,60): # totally arbitrary, just looks to be unused on black-mesa
19 filename = '/dev/loop%d'%i
20 if 0 == len(file(filename).read(1)):
21 loopdevice = filename # it's empty
23 if loopdevice is not None:
24 call(['losetup', '-o', str(offset), loopdevice, source])
26 raise RuntimeError('out of loop devices for copying VM image: too many at once?')
28 os.unlink(lockfilename) #unlock
30 # XX this means we can duplicate 28 at once. Since it takes around 30s,
31 # this seems like an adequate capacity.
33 def frob_copy_in_vm(target, *args):
34 '''UNUSED: maybe we'll use this someday; it does isolate the frobber.'''
35 # 1. prepare arguments volume
36 args_volume = prefix+target+'_args'
37 args_device = '/dev/xenvg/' + args_volume
38 check_call(['/sbin/lvcreate', 'xenvg', '--name', args_volume, '--size', '4K'])
39 file(args_device, 'w').write('\n'.join(args) + '\n')
41 # 2. invoke frobber vm
42 copier_device = '/dev/xenvg/d_wert_hda'
43 check_call(['/usr/sbin/xm', 'create', 'sipb-database',
44 'machine_name='+target,
45 'disks=' + ' '.join(['phy:'+copier_device+',hda,w',
46 'phy:'+target_device+',hdc,w',
47 'phy:'+args_device+',hdd,w'])])
49 # XXX should check_call(['/sbin/lvremove', '-f', 'xenvg/'+args_volume])
51 def frob_copy(target, hostname, rootpw):
52 """target should be an LV device filename"""
54 fs = losetup(target, 32256)
55 mntdir = tempfile.mkdtemp('', 'auto-install.frob.', '/tmp')
56 call(['mount', '-t', 'ext3', fs, mntdir])
58 call(['/usr/sbin/chroot', mntdir, '/post-copy', hostname, rootpw])
60 call(['umount', mntdir])
62 call(['losetup', '-d', fs])
64 def duplicate_by_vm(source, target, rootpw, nodd=False, nofrob=False):
65 # source, target should be machine names
67 # 1. copy (by dd) source to target
68 source_device = '/dev/xenvg/' + prefix + source + '_hda'
69 target_device = '/dev/xenvg/' + prefix + target + '_hda'
71 check_call(['/bin/dd', 'bs=1M', 'conv=nocreat',
72 'if='+source_device, 'of='+target_device])
75 frob_copy(target_device, target, rootpw)
80 os.environ['PATH'] = '/usr/sbin:/usr/bin:/sbin:/bin'
81 if subcommand == 'lvcopy':
84 if args[0].startswith('--'):
85 kwargs[args[0][2:]] = True
89 print >>sys.stderr, argv[0]+': bad argument list'
92 duplicate_by_vm(*args, **kwargs)
93 elif subcommand == 'test':
96 print >>sys.stderr, argv[0]+": unknown subcommand: "+subcommand
100 if __name__ == '__main__':
101 sys.exit(main(*sys.argv))