Works, more or less.
This commit is contained in:
+121
-89
@@ -32,7 +32,6 @@ from stat import ST_MODE
|
||||
from os.path import abspath
|
||||
from sys import exit, argv
|
||||
from glob import glob
|
||||
from urllib import urlretrieve
|
||||
from subprocess import check_output, call, Popen
|
||||
from tempfile import mkdtemp
|
||||
from time import time, strftime, localtime
|
||||
@@ -117,15 +116,9 @@ def findiso( flavor ):
|
||||
url = isoURLs[ flavor ]
|
||||
name = path.basename( url )
|
||||
iso = path.join( VMImageDir, name )
|
||||
if path.exists( iso ):
|
||||
# Detect race condition with multiple builds
|
||||
perms = stat( iso )[ ST_MODE ] & 0777
|
||||
if perms != 0444:
|
||||
raise Exception( 'Error - %s is writable ' % iso +
|
||||
'; are multiple builds running?' )
|
||||
else:
|
||||
if not path.exists( iso ) or ( stat( iso )[ ST_MODE ] & 0777 != 0444 ):
|
||||
log( '* Retrieving', url )
|
||||
urlretrieve( url, iso )
|
||||
run( 'curl -C - -o %s %s' % ( iso, url ) )
|
||||
# Write-protect iso, signaling it is complete
|
||||
log( '* Write-protecting iso', iso)
|
||||
os.chmod( iso, 0444 )
|
||||
@@ -156,30 +149,30 @@ def detachNBD( nbd ):
|
||||
srun( 'qemu-nbd -d ' + nbd )
|
||||
|
||||
|
||||
def kernelpath( flavor ):
|
||||
"Return kernel path for flavor"
|
||||
return path.join( VMImageDir, flavor + '-vmlinuz' )
|
||||
|
||||
|
||||
def extractKernel( image, kernel ):
|
||||
def extractKernel( image, flavor ):
|
||||
"Extract kernel from base image"
|
||||
nbd = attachNBD( image )
|
||||
kernel = path.join( VMImageDir, flavor + '-vmlinuz' )
|
||||
if path.exists( kernel ) and ( stat( image )[ ST_MODE ] & 0777 ) == 0444:
|
||||
return kernel
|
||||
log( '* Extracting kernel to', kernel )
|
||||
nbd = attachNBD( image, flags='-r' )
|
||||
print srun( 'partx ' + nbd )
|
||||
# Assume kernel is in partition 1/boot/vmlinuz*generic for now
|
||||
part = nbd + 'p1'
|
||||
mnt = mkdtemp()
|
||||
srun( 'mount %s %s' % ( part, mnt ) )
|
||||
kernsrc = glob( '%s/boot/vmlinuz*generic' % mnt )[ 0 ]
|
||||
run( 'cp %s %s' % ( kernsrc, kernel ) )
|
||||
run( 'sudo cp %s %s' % ( kernsrc, kernel ) )
|
||||
run( 'sudo chmod 0444 ' + kernel )
|
||||
srun( 'umount ' + mnt )
|
||||
run( 'rmdir ' + mnt )
|
||||
detachNBD( image )
|
||||
detachNBD( nbd )
|
||||
return kernel
|
||||
|
||||
|
||||
def findBaseImage( flavor, size='8G' ):
|
||||
"Return base VM image and kernel, creating them if needed"
|
||||
image = path.join( VMImageDir, flavor + '-base.img' )
|
||||
kernel = path.join( VMImageDir, flavor + '-vmlinuz' )
|
||||
if path.exists( image ):
|
||||
# Detect race condition with multiple builds
|
||||
perms = stat( image )[ ST_MODE ] & 0777
|
||||
@@ -193,79 +186,104 @@ def findBaseImage( flavor, size='8G' ):
|
||||
log( '* Creating image file', image )
|
||||
run( 'qemu-img create %s %s' % ( image, size ) )
|
||||
installUbuntu( iso, image )
|
||||
log( '* Extracting kernel to', kernel )
|
||||
extractKernel( image, kernel )
|
||||
# Write-protect image, also signaling it is complete
|
||||
log( '* Write-protecting image', image)
|
||||
os.chmod( image, 0444 )
|
||||
log( '* Using base image', image )
|
||||
kernel = extractKernel( image, flavor )
|
||||
log( '* Using base image', image, 'and kernel', kernel )
|
||||
return image, kernel
|
||||
|
||||
|
||||
# Kickstart and Preseed files for Ubuntu/Debian installer
|
||||
#
|
||||
# Comments: this is really clunky and painful. If Ubuntu
|
||||
# gets their act together and supports kickstart a bit better
|
||||
# then we can get rid of preseed and even use this as a
|
||||
# Fedora installer as well.
|
||||
#
|
||||
# Another annoying thing about Ubuntu is that it can't just
|
||||
# install a normal system from the iso - it has to download
|
||||
# junk from the internet, making this house of cards even
|
||||
# more precarious.
|
||||
|
||||
KickstartText ="""
|
||||
#Generated by Kickstart Configurator
|
||||
#platform=x86
|
||||
|
||||
#System language
|
||||
lang en_US
|
||||
#Language modules to install
|
||||
langsupport en_US
|
||||
#System keyboard
|
||||
keyboard us
|
||||
#System mouse
|
||||
mouse
|
||||
#System timezone
|
||||
timezone America/Los_Angeles
|
||||
#Root password
|
||||
rootpw --disabled
|
||||
#Initial user
|
||||
user mininet --fullname "mininet" --password "mininet"
|
||||
#Use text mode install
|
||||
text
|
||||
#Install OS instead of upgrade
|
||||
install
|
||||
#Use CDROM installation media
|
||||
cdrom
|
||||
#System bootloader configuration
|
||||
bootloader --location=mbr
|
||||
#Clear the Master Boot Record
|
||||
zerombr yes
|
||||
#Partition clearing information
|
||||
clearpart --all --initlabel
|
||||
#Automatic partitioning
|
||||
autopart
|
||||
#System authorization infomation
|
||||
auth --useshadow --enablemd5
|
||||
#Firewall configuration
|
||||
firewall --disabled
|
||||
#Do not configure the X Window System
|
||||
skipx
|
||||
"""
|
||||
|
||||
# Tell the Ubuntu/Debian installer to stop asking stupid questions
|
||||
|
||||
PreseedText = """
|
||||
d-i mirror/country string manual
|
||||
d-i mirror/http/hostname string mirrors.kernel.org
|
||||
d-i mirror/http/directory string /ubuntu
|
||||
d-i mirror/http/proxy string
|
||||
d-i partman/confirm_write_new_label boolean true
|
||||
d-i partman/choose_partition select finish
|
||||
d-i partman/confirm boolean true
|
||||
d-i partman/confirm_nooverwrite boolean true
|
||||
d-i user-setup/allow-password-weak boolean true
|
||||
d-i finish-install/reboot_in_progress note
|
||||
d-i debian-installer/exit/poweroff boolean true
|
||||
"""
|
||||
|
||||
def makeKickstartFloppy():
|
||||
"Create and return kickstart floppy, kickstart, preseed"
|
||||
kickstart = 'ks.cfg'
|
||||
kstext = '\n'.join( [ '#Generated by Kickstart Configurator',
|
||||
'#platform=x86',
|
||||
'#System language',
|
||||
'lang en_US',
|
||||
'#Language modules to install',
|
||||
'langsupport en_US',
|
||||
'#System keyboard',
|
||||
'keyboard us',
|
||||
'#System mouse',
|
||||
'mouse',
|
||||
'#System timezone',
|
||||
'timezone America/Los_Angeles',
|
||||
'#Root password',
|
||||
'rootpw --disabled',
|
||||
'#Initial user'
|
||||
'user mininet --fullname "mininet" --password "mininet"',
|
||||
'#Use text mode install',
|
||||
'text',
|
||||
'#Install OS instead of upgrade',
|
||||
'install',
|
||||
'#Use CDROM installation media',
|
||||
'cdrom',
|
||||
'#System bootloader configuration',
|
||||
'bootloader --location=mbr',
|
||||
'#Clear the Master Boot Record',
|
||||
'zerombr yes',
|
||||
'#Partition clearing information',
|
||||
'clearpart --all --initlabel',
|
||||
'#Automatic partitioning',
|
||||
'autopart',
|
||||
'#System authorization infomation',
|
||||
'auth --useshadow --enablemd5',
|
||||
'#Firewall configuration',
|
||||
'firewall --disabled',
|
||||
'#Do not configure the X Window System',
|
||||
'skipx', '' ] )
|
||||
with open( kickstart, 'w' ) as f:
|
||||
f.write( kstext )
|
||||
f.write( KickstartText )
|
||||
preseed = 'ks.preseed'
|
||||
pstext = '\n'.join( [ 'd-i partman/confirm_write_new_label boolean true',
|
||||
'd-i partman/choose_partition select finish',
|
||||
'd-i partman/confirm boolean true',
|
||||
'd-i partman/confirm_nooverwrite boolean true',
|
||||
'd-i user-setup/allow-password-weak boolean true' ] )
|
||||
with open( preseed, 'w' ) as f:
|
||||
f.write( pstext )
|
||||
f.write( PreseedText )
|
||||
# Create floppy and copy files to it
|
||||
floppy = 'ksfloppy.img'
|
||||
run( 'qemu-img create %s 1M' % floppy )
|
||||
run( 'qemu-img create %s 1440k' % floppy )
|
||||
run( 'mkfs -t msdos ' + floppy )
|
||||
run( 'mcopy -i %s %s ::/' % ( floppy, kickstart ) )
|
||||
run( 'mcopy -i %s %s ::/' % ( floppy, preseed ) )
|
||||
log( '* Created floppy image %s containing %s and %s' %
|
||||
( floppy, kickstart, preseed ) )
|
||||
return floppy, kickstart, preseed
|
||||
|
||||
|
||||
def kvmFor( name ):
|
||||
"Guess kvm version for file name"
|
||||
if 'amd64' in name:
|
||||
if '64' in name:
|
||||
kvm = 'qemu-system-x86_64'
|
||||
elif 'i386' in name:
|
||||
elif 'i386' in name or '32' in name:
|
||||
kvm = 'qemu-system-i386'
|
||||
else:
|
||||
log( "Error: can't discern CPU for file name", name )
|
||||
@@ -273,36 +291,49 @@ def kvmFor( name ):
|
||||
return kvm
|
||||
|
||||
|
||||
def installUbuntu( iso, image ):
|
||||
def installUbuntu( iso, image, logfilename='install.log' ):
|
||||
"Install Ubuntu from iso onto image"
|
||||
global pexpect
|
||||
import pexpect
|
||||
kvm = kvmFor( iso )
|
||||
floppy, kickstart, preseed = makeKickstartFloppy()
|
||||
# Mount iso so we can use its kernel
|
||||
mnt = mkdtemp()
|
||||
srun( 'mount %s %s' % ( iso, mnt ) )
|
||||
kernel = mnt + 'install/vmlinuz'
|
||||
srun( 'ls ' + mnt )
|
||||
kernel = path.join( mnt, 'install/vmlinuz' )
|
||||
initrd = path.join( mnt, 'install/initrd.gz' )
|
||||
cmd = [ 'sudo', kvm,
|
||||
'-machine accel=kvm',
|
||||
'-machine', 'accel=kvm',
|
||||
'-nographic',
|
||||
'-netdev user,id=mnbuild',
|
||||
'-device virtio-net,netdev=mnbuild',
|
||||
'-m 1024',
|
||||
'-k en-us',
|
||||
'-cdrom', iso,
|
||||
'-drive file=%s,if=virtio' % image,
|
||||
'-netdev', 'user,id=mnbuild',
|
||||
'-device', 'virtio-net,netdev=mnbuild',
|
||||
'-m', '1024',
|
||||
'-k', 'en-us',
|
||||
'-fda', floppy,
|
||||
'-drive', 'file=%s,if=virtio' % image,
|
||||
'-cdrom', iso,
|
||||
'-kernel', kernel,
|
||||
'-append "root=/dev/vda1 init=/sbin/init console=ttyS0' +
|
||||
'ks=floppy:/' + kickstart +
|
||||
'preseed/file=floppy://' + preseed + '"' ]
|
||||
cmd = ' '.join( cmd )
|
||||
'-initrd', initrd,
|
||||
'-append',
|
||||
' ks=floppy:/' + kickstart +
|
||||
' preseed/file=floppy://' + preseed +
|
||||
' console=ttyS0' ]
|
||||
ubuntuStart = time()
|
||||
log( '* INSTALLING UBUNTU FROM', iso, 'ONTO', image )
|
||||
log( cmd )
|
||||
run( cmd )
|
||||
log( ' '.join( cmd ) )
|
||||
log( '* logging to', abspath( logfilename ) )
|
||||
logfile = open( logfilename, 'w' )
|
||||
vm = Popen( cmd, stdout=logfile, stderr=logfile )
|
||||
log( '* Waiting for installation to complete')
|
||||
vm.wait()
|
||||
logfile.close()
|
||||
elapsed = time() - ubuntuStart
|
||||
# Unmount iso and clean up
|
||||
srun( 'umount ' + mnt )
|
||||
run( 'rmdir ' + mnt )
|
||||
log( '* UBUNTU INSTALLATION COMPLETED FOR', image )
|
||||
log( '* Ubuntu installation completed in %.2f seconds ' % elapsed )
|
||||
|
||||
|
||||
def boot( cow, kernel, logfile ):
|
||||
@@ -356,6 +387,8 @@ def interact( vm ):
|
||||
vm.expect( prompt )
|
||||
log( '* Running VM install script' )
|
||||
vm.sendline( 'bash install-mininet-vm.sh' )
|
||||
vm.expect ( 'password for mininet: ' )
|
||||
vm.sendline( 'mininet' )
|
||||
log( '* Waiting for script to complete... ' )
|
||||
# Gigantic timeout for now ;-(
|
||||
vm.expect( 'Done preparing Mininet', timeout=3600 )
|
||||
@@ -380,7 +413,7 @@ def interact( vm ):
|
||||
vm.sendline( 'sync; sudo shutdown -h now' )
|
||||
log( '* Waiting for EOF/shutdown' )
|
||||
vm.read()
|
||||
log( '* Interaction complete' )
|
||||
log( '* Interaction complete' )
|
||||
|
||||
|
||||
def cleanup():
|
||||
@@ -412,14 +445,13 @@ def build( flavor='raring32server' ):
|
||||
vm = boot( volume, kernel, logfile )
|
||||
interact( vm )
|
||||
vmdk = convert( volume, basename=flavor )
|
||||
log( '* Converted VM image stored as', vmdk )
|
||||
log( '* Converted VM image stored as', abspath( vmdk ) )
|
||||
end = time()
|
||||
elapsed = end - start
|
||||
log( '* Results logged to', abspath( logfile.name ) )
|
||||
log( '* Completed in %.2f seconds' % elapsed )
|
||||
log( '* %s VM build DONE!!!!! :D' % flavor )
|
||||
log( '* ' )
|
||||
os.chdir( '..' )
|
||||
os.chdir( '..' )
|
||||
|
||||
|
||||
def listFlavors():
|
||||
|
||||
Reference in New Issue
Block a user