Works, more or less.

This commit is contained in:
Bob Lantz
2013-08-23 20:33:25 -07:00
parent fa1758b950
commit f605a4e430
+118 -86
View File
@@ -32,7 +32,6 @@ from stat import ST_MODE
from os.path import abspath from os.path import abspath
from sys import exit, argv from sys import exit, argv
from glob import glob from glob import glob
from urllib import urlretrieve
from subprocess import check_output, call, Popen from subprocess import check_output, call, Popen
from tempfile import mkdtemp from tempfile import mkdtemp
from time import time, strftime, localtime from time import time, strftime, localtime
@@ -117,15 +116,9 @@ def findiso( flavor ):
url = isoURLs[ flavor ] url = isoURLs[ flavor ]
name = path.basename( url ) name = path.basename( url )
iso = path.join( VMImageDir, name ) iso = path.join( VMImageDir, name )
if path.exists( iso ): if not path.exists( iso ) or ( stat( iso )[ ST_MODE ] & 0777 != 0444 ):
# 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:
log( '* Retrieving', url ) log( '* Retrieving', url )
urlretrieve( url, iso ) run( 'curl -C - -o %s %s' % ( iso, url ) )
# Write-protect iso, signaling it is complete # Write-protect iso, signaling it is complete
log( '* Write-protecting iso', iso) log( '* Write-protecting iso', iso)
os.chmod( iso, 0444 ) os.chmod( iso, 0444 )
@@ -156,30 +149,30 @@ def detachNBD( nbd ):
srun( 'qemu-nbd -d ' + nbd ) srun( 'qemu-nbd -d ' + nbd )
def kernelpath( flavor ): def extractKernel( image, flavor ):
"Return kernel path for flavor"
return path.join( VMImageDir, flavor + '-vmlinuz' )
def extractKernel( image, kernel ):
"Extract kernel from base image" "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 ) print srun( 'partx ' + nbd )
# Assume kernel is in partition 1/boot/vmlinuz*generic for now # Assume kernel is in partition 1/boot/vmlinuz*generic for now
part = nbd + 'p1' part = nbd + 'p1'
mnt = mkdtemp() mnt = mkdtemp()
srun( 'mount %s %s' % ( part, mnt ) ) srun( 'mount %s %s' % ( part, mnt ) )
kernsrc = glob( '%s/boot/vmlinuz*generic' % mnt )[ 0 ] 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 ) srun( 'umount ' + mnt )
run( 'rmdir ' + mnt ) run( 'rmdir ' + mnt )
detachNBD( image ) detachNBD( nbd )
return kernel
def findBaseImage( flavor, size='8G' ): def findBaseImage( flavor, size='8G' ):
"Return base VM image and kernel, creating them if needed" "Return base VM image and kernel, creating them if needed"
image = path.join( VMImageDir, flavor + '-base.img' ) image = path.join( VMImageDir, flavor + '-base.img' )
kernel = path.join( VMImageDir, flavor + '-vmlinuz' )
if path.exists( image ): if path.exists( image ):
# Detect race condition with multiple builds # Detect race condition with multiple builds
perms = stat( image )[ ST_MODE ] & 0777 perms = stat( image )[ ST_MODE ] & 0777
@@ -193,79 +186,104 @@ def findBaseImage( flavor, size='8G' ):
log( '* Creating image file', image ) log( '* Creating image file', image )
run( 'qemu-img create %s %s' % ( image, size ) ) run( 'qemu-img create %s %s' % ( image, size ) )
installUbuntu( iso, image ) installUbuntu( iso, image )
log( '* Extracting kernel to', kernel )
extractKernel( image, kernel )
# Write-protect image, also signaling it is complete # Write-protect image, also signaling it is complete
log( '* Write-protecting image', image) log( '* Write-protecting image', image)
os.chmod( image, 0444 ) os.chmod( image, 0444 )
log( '* Using base image', image ) kernel = extractKernel( image, flavor )
log( '* Using base image', image, 'and kernel', kernel )
return image, 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(): def makeKickstartFloppy():
"Create and return kickstart floppy, kickstart, preseed" "Create and return kickstart floppy, kickstart, preseed"
kickstart = 'ks.cfg' 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: with open( kickstart, 'w' ) as f:
f.write( kstext ) f.write( KickstartText )
preseed = 'ks.preseed' 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: with open( preseed, 'w' ) as f:
f.write( pstext ) f.write( PreseedText )
# Create floppy and copy files to it # Create floppy and copy files to it
floppy = 'ksfloppy.img' 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, kickstart ) )
run( 'mcopy -i %s %s ::/' % ( floppy, preseed ) ) run( 'mcopy -i %s %s ::/' % ( floppy, preseed ) )
log( '* Created floppy image %s containing %s and %s' %
( floppy, kickstart, preseed ) )
return floppy, kickstart, preseed return floppy, kickstart, preseed
def kvmFor( name ): def kvmFor( name ):
"Guess kvm version for file name" "Guess kvm version for file name"
if 'amd64' in name: if '64' in name:
kvm = 'qemu-system-x86_64' kvm = 'qemu-system-x86_64'
elif 'i386' in name: elif 'i386' in name or '32' in name:
kvm = 'qemu-system-i386' kvm = 'qemu-system-i386'
else: else:
log( "Error: can't discern CPU for file name", name ) log( "Error: can't discern CPU for file name", name )
@@ -273,36 +291,49 @@ def kvmFor( name ):
return kvm return kvm
def installUbuntu( iso, image ): def installUbuntu( iso, image, logfilename='install.log' ):
"Install Ubuntu from iso onto image" "Install Ubuntu from iso onto image"
global pexpect
import pexpect
kvm = kvmFor( iso ) kvm = kvmFor( iso )
floppy, kickstart, preseed = makeKickstartFloppy() floppy, kickstart, preseed = makeKickstartFloppy()
# Mount iso so we can use its kernel # Mount iso so we can use its kernel
mnt = mkdtemp() mnt = mkdtemp()
srun( 'mount %s %s' % ( iso, mnt ) ) 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, cmd = [ 'sudo', kvm,
'-machine accel=kvm', '-machine', 'accel=kvm',
'-nographic', '-nographic',
'-netdev user,id=mnbuild', '-netdev', 'user,id=mnbuild',
'-device virtio-net,netdev=mnbuild', '-device', 'virtio-net,netdev=mnbuild',
'-m 1024', '-m', '1024',
'-k en-us', '-k', 'en-us',
'-cdrom', iso,
'-drive file=%s,if=virtio' % image,
'-fda', floppy, '-fda', floppy,
'-drive', 'file=%s,if=virtio' % image,
'-cdrom', iso,
'-kernel', kernel, '-kernel', kernel,
'-append "root=/dev/vda1 init=/sbin/init console=ttyS0' + '-initrd', initrd,
'-append',
' ks=floppy:/' + kickstart + ' ks=floppy:/' + kickstart +
'preseed/file=floppy://' + preseed + '"' ] ' preseed/file=floppy://' + preseed +
cmd = ' '.join( cmd ) ' console=ttyS0' ]
ubuntuStart = time()
log( '* INSTALLING UBUNTU FROM', iso, 'ONTO', image ) log( '* INSTALLING UBUNTU FROM', iso, 'ONTO', image )
log( cmd ) log( ' '.join( cmd ) )
run( 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 # Unmount iso and clean up
srun( 'umount ' + mnt ) srun( 'umount ' + mnt )
run( 'rmdir ' + mnt ) run( 'rmdir ' + mnt )
log( '* UBUNTU INSTALLATION COMPLETED FOR', image ) log( '* UBUNTU INSTALLATION COMPLETED FOR', image )
log( '* Ubuntu installation completed in %.2f seconds ' % elapsed )
def boot( cow, kernel, logfile ): def boot( cow, kernel, logfile ):
@@ -356,6 +387,8 @@ def interact( vm ):
vm.expect( prompt ) vm.expect( prompt )
log( '* Running VM install script' ) log( '* Running VM install script' )
vm.sendline( 'bash install-mininet-vm.sh' ) vm.sendline( 'bash install-mininet-vm.sh' )
vm.expect ( 'password for mininet: ' )
vm.sendline( 'mininet' )
log( '* Waiting for script to complete... ' ) log( '* Waiting for script to complete... ' )
# Gigantic timeout for now ;-( # Gigantic timeout for now ;-(
vm.expect( 'Done preparing Mininet', timeout=3600 ) vm.expect( 'Done preparing Mininet', timeout=3600 )
@@ -412,13 +445,12 @@ def build( flavor='raring32server' ):
vm = boot( volume, kernel, logfile ) vm = boot( volume, kernel, logfile )
interact( vm ) interact( vm )
vmdk = convert( volume, basename=flavor ) vmdk = convert( volume, basename=flavor )
log( '* Converted VM image stored as', vmdk ) log( '* Converted VM image stored as', abspath( vmdk ) )
end = time() end = time()
elapsed = end - start elapsed = end - start
log( '* Results logged to', abspath( logfile.name ) ) log( '* Results logged to', abspath( logfile.name ) )
log( '* Completed in %.2f seconds' % elapsed ) log( '* Completed in %.2f seconds' % elapsed )
log( '* %s VM build DONE!!!!! :D' % flavor ) log( '* %s VM build DONE!!!!! :D' % flavor )
log( '* ' )
os.chdir( '..' ) os.chdir( '..' )