lib/veewee/session.rb in HeSYINUvSBZfxqA-veewee-0.2.0.2 vs lib/veewee/session.rb in HeSYINUvSBZfxqA-veewee-0.203.1
- old
+ new
@@ -5,23 +5,20 @@
require 'open-uri'
require 'progressbar'
require 'highline/import'
require 'tempfile'
require 'virtualbox'
-require 'virtualbox/abstract_model'
-require 'virtualbox/ext/byte_normalizer'
-
module Veewee
class Session
- attr_accessor :veewee_dir
- attr_accessor :definition_dir
- attr_accessor :template_dir
- attr_accessor :iso_dir
- attr_accessor :name
- attr_accessor :definition
+ attr_accessor :veewee_dir
+ attr_accessor :definition_dir
+ attr_accessor :template_dir
+ attr_accessor :iso_dir
+ attr_accessor :name
+ attr_accessor :definition
def self.setenv(env)
@veewee_dir=env[:veewee_dir]
@definition_dir=env[:definition_dir]
@template_dir=env[:template_dir]
@@ -74,15 +71,15 @@
FileUtils.cp_r(File.join(@template_dir,template_name,'.'),File.join(@definition_dir,boxname))
puts "The basebox '#{boxname}' has been successfully created from the template ''#{template_name}'"
puts "You can now edit the definition files stored in definitions/#{boxname}"
puts "or build the box with:"
if (options["format"]=='vagrant')
- puts "vagrant basebox build '#{boxname}'"
- end
- if (options["format"]=='veewee')
- puts "veewee build '#{boxname}'"
- end
+ puts "vagrant basebox build '#{boxname}'"
+ end
+ if (options["format"]=='veewee')
+ puts "veewee build '#{boxname}'"
+ end
end
@@ -90,11 +87,11 @@
def self.definition_exists?(boxname)
if File.directory?(File.join(@definition_dir,boxname))
if File.exists?(File.join(@definition_dir,boxname,'definition.rb'))
return true
else
- return false
+ return false
end
else
return false
end
@@ -112,41 +109,41 @@
end
end
def self.list_templates( options = { :format => 'vagrant'})
puts "The following templates are available:"
- subdirs=Dir.glob("#{@template_dir}/*")
+ subdirs=Dir.glob("#{@template_dir}/*").sort_by {|f| File.basename f}
subdirs.each do |sub|
if File.directory?("#{sub}")
definition=Dir.glob("#{sub}/definition.rb")
if definition.length!=0
name=sub.sub(/#{@template_dir}\//,'')
- if (options[:format]=='vagrant')
- puts "vagrant basebox define '<boxname>' '#{name}'"
- end
+ if (options[:format]=='vagrant')
+ puts "vagrant basebox define '<boxname>' '#{name}'"
+ end
if (options[:format]=='veewee')
puts "veewee define '<boxname>' '#{name}'"
end
end
end
end
end
def self.list_boxes
- puts "Not yet implemented"
+ puts "Not yet implemented"
end
def self.list_definitions
- puts "The following defined baseboxes exist:"
- subdirs=Dir.glob("#{@definition_dir}/*")
- subdirs.each do |sub|
- puts "- "+File.basename(sub)
- end
+ puts "The following defined baseboxes exist:"
+ subdirs=Dir.glob("#{@definition_dir}/*")
+ subdirs.each do |sub|
+ puts "- "+File.basename(sub)
+ end
end
def self.clean
- puts "Not yet implemented"
+ puts "Not yet implemented"
end
def self.verify_iso(filename,autodownload = false)
if File.exists?(File.join(@iso_dir,filename))
puts
@@ -174,28 +171,28 @@
puts "- then re-run the command"
puts
exit
else
- question=ask("Download? (Yes/No)") {|q| q.default="No"}
- if question.downcase == "yes"
- if !File.exists?(@iso_dir)
- puts "Creating an iso directory"
- FileUtils.mkdir(@iso_dir)
- end
-
- download_progress(@definition[:iso_src],full_path)
- else
- puts "You have choosen for manual download: "
- puts "curl -C - -L '#{@definition[:iso_src]}' -o '#{rel_path}'"
- puts "md5 '#{rel_path}' "
- puts
- exit
+ question=ask("Download? (Yes/No)") {|q| q.default="No"}
+ if question.downcase == "yes"
+ if !File.exists?(@iso_dir)
+ puts "Creating an iso directory"
+ FileUtils.mkdir(@iso_dir)
end
+ download_progress(@definition[:iso_src],full_path)
+ else
+ puts "You have choosen for manual download: "
+ puts "curl -C - -L '#{@definition[:iso_src]}' -o '#{rel_path}'"
+ puts "md5 '#{rel_path}' "
+ puts
+ exit
end
+
end
+ end
end
def self.export_box(boxname)
#Now we have to load the definition (reads definition.rb)
@@ -207,199 +204,205 @@
add_ssh_nat_mapping(boxname)
end
def self.remove_box(boxname)
- puts "Not yet implemented"
+ puts "Not yet implemented"
end
def self.build(boxname,options)
- options = { "force" => false, "format" => "vagrant", "nogui" => false }.merge(options)
+ options = { "force" => false, "format" => "vagrant", "nogui" => false }.merge(options)
- #Now we have to load the definition (reads definition.rb)
- load_definition(boxname)
+ #Now we have to load the definition (reads definition.rb)
+ load_definition(boxname)
- #Command to execute locally
- @vboxcmd=determine_vboxcmd
+ #Command to execute locally
+ @vboxcmd=determine_vboxcmd
- ssh_options={ :user => @definition[:ssh_user], :port => @definition[:ssh_host_port], :password => @definition[:ssh_password],
- :timeout => @definition[:ssh_timeout]}
+ ssh_options={ :user => @definition[:ssh_user], :port => @definition[:ssh_host_port], :password => @definition[:ssh_password],
+ :timeout => @definition[:ssh_timeout]}
- #Suppress those annoying virtualbox messages
- suppress_messages
+ #Suppress those annoying virtualbox messages
+ suppress_messages
- vm=VirtualBox::VM.find(boxname)
+ vm=VirtualBox::VM.find(boxname)
- if (!vm.nil? && (vm.saved?))
- puts "Removing save state"
- vm.discard_state
- vm.reload
- end
+ if (!vm.nil? && (vm.saved?))
+ puts "Removing save state"
+ vm.discard_state
+ vm.reload
+ end
- if (!vm.nil? && !(vm.powered_off?))
- puts "Shutting down vm #{boxname}"
- #We force it here, maybe vm.shutdown is cleaner
- begin
+ if (!vm.nil? && !(vm.powered_off?))
+ puts "Shutting down vm #{boxname}"
+ #We force it here, maybe vm.shutdown is cleaner
+ begin
- vm.stop
- rescue VirtualBox::Exceptions::InvalidVMStateException
- puts "There was problem sending the stop command because the machine is in an Invalid state"
- puts "Please verify leftovers from a previous build in your vm folder"
- exit
+ vm.stop
+ rescue VirtualBox::Exceptions::InvalidVMStateException
+ puts "There was problem sending the stop command because the machine is in an Invalid state"
+ puts "Please verify leftovers from a previous build in your vm folder"
+ exit
+ end
+ sleep 3
end
- sleep 3
- end
- verify_iso(@definition[:iso_file])
+ verify_iso(@definition[:iso_file])
- if (options["force"]==false)
- else
- puts "Forcing build by destroying #{boxname} machine"
- destroy_vm(boxname)
- end
+ if (options["force"]==false)
+ else
+ puts "Forcing build by destroying #{boxname} machine"
+ destroy_vm(boxname)
+ end
- if Veewee::Utils.is_port_open?("localhost", @definition[:ssh_host_port])
- puts "Hmm, the port #{@definition[:ssh_host_port]} is open. And we shut down?"
- exit
- end
+ if Veewee::Utils.is_port_open?("localhost", @definition[:ssh_host_port])
+ puts "Hmm, the port #{@definition[:ssh_host_port]} is open. And we shut down?"
+ exit
+ end
- checksums=calculate_checksums(@definition,boxname)
+ checksums=calculate_checksums(@definition,boxname)
- #Create the Virtualmachine and set all the memory and other stuff
- create_vm(boxname)
+ transaction(boxname,"0-initial-#{checksums[0]}",checksums) do
- #Create a disk with the same name as the boxname
- create_disk(boxname)
+ #Create the Virtualmachine and set all the memory and other stuff
+ create_vm(boxname)
+ #Create a disk with the same name as the boxname
+ create_disk(boxname)
- #These command actually call the commandline of Virtualbox, I hope to use the virtualbox-ruby library in the future
- add_ide_controller(boxname)
- add_sata_controller(boxname)
- attach_disk(boxname)
- mount_isofile(boxname,@definition[:iso_file])
- add_ssh_nat_mapping(boxname)
- #Starting machine
+ #These command actually call the commandline of Virtualbox, I hope to use the virtualbox-ruby library in the future
+ add_ide_controller(boxname)
+ add_sata_controller(boxname)
+ attach_disk(boxname)
+ mount_isofile(boxname,@definition[:iso_file])
+ add_ssh_nat_mapping(boxname)
- if (options["nogui"]==true)
- start_vm(boxname,"vrdp")
- else
- start_vm(boxname,"gui")
- end
+ #Starting machine
- #waiting for it to boot
- puts "Waiting for the machine to boot"
- sleep @definition[:boot_wait].to_i
+ if (options["nogui"]==true)
+ start_vm(boxname,"vrdp")
+ else
+ start_vm(boxname,"gui")
+ end
- Veewee::Scancode.send_sequence("#{@vboxcmd}","#{boxname}",@definition[:boot_cmd_sequence],@definition[:kickstart_port])
+ #waiting for it to boot
+ puts "Waiting for the machine to boot"
+ sleep @definition[:boot_wait].to_i
- kickstartfile=@definition[:kickstart_file]
- if kickstartfile.nil? || kickstartfile.length == 0
- puts "Skipping webserver as no kickstartfile was specified"
- else
- puts "Starting a webserver on port #{@definition[:kickstart_port]}"
- #:kickstart_port => "7122", :kickstart_ip => self.local_ip, :kickstart_timeout => 1000,:kickstart_file => "preseed.cfg",
- if kickstartfile.is_a? String
- Veewee::Web.wait_for_request(kickstartfile,{:port => @definition[:kickstart_port],
- :host => @definition[:kickstart_ip], :timeout => @definition[:kickstart_timeout],
- :web_dir => File.join(@definition_dir,boxname)})
- end
- if kickstartfile.is_a? Array
- kickstartfiles=kickstartfile
- kickstartfiles.each do |kickfile|
- Veewee::Web.wait_for_request(kickfile,{:port => @definition[:kickstart_port],
+ Veewee::Scancode.send_sequence("#{@vboxcmd}","#{boxname}",@definition[:boot_cmd_sequence],@definition[:kickstart_port])
+
+ kickstartfile=@definition[:kickstart_file]
+ if kickstartfile.nil? || kickstartfile.length == 0
+ puts "Skipping webserver as no kickstartfile was specified"
+ else
+ puts "Starting a webserver on port #{@definition[:kickstart_port]}"
+ #:kickstart_port => "7122", :kickstart_ip => self.local_ip, :kickstart_timeout => 1000,:kickstart_file => "preseed.cfg",
+ if kickstartfile.is_a? String
+ Veewee::Web.wait_for_request(kickstartfile,{:port => @definition[:kickstart_port],
:host => @definition[:kickstart_ip], :timeout => @definition[:kickstart_timeout],
:web_dir => File.join(@definition_dir,boxname)})
- end
- end
- end
+ end
+ if kickstartfile.is_a? Array
+ kickstartfiles=kickstartfile
+ kickstartfiles.each do |kickfile|
+ Veewee::Web.wait_for_request(kickfile,{:port => @definition[:kickstart_port],
+ :host => @definition[:kickstart_ip], :timeout => @definition[:kickstart_timeout],
+ :web_dir => File.join(@definition_dir,boxname)})
+ end
+ end
+ end
- Veewee::Ssh.when_ssh_login_works("localhost",ssh_options) do
- #Transfer version of Virtualbox to $HOME/.vbox_version
- versionfile=Tempfile.open("vbox.version")
- versionfile.puts "#{VirtualBox::Global.global.lib.virtualbox.version.split('_')[0]}"
- versionfile.rewind
- begin
- Veewee::Ssh.transfer_file("localhost",versionfile.path,".vbox_version", ssh_options)
- rescue RuntimeError
- puts "error transfering file, possible not enough permissions to write?"
- exit
- end
- puts ""
- versionfile.close
- versionfile.delete
- end
+ Veewee::Ssh.when_ssh_login_works("localhost",ssh_options) do
+ #Transfer version of Virtualbox to $HOME/.vbox_version
+ versionfile=Tempfile.open("vbox.version")
+ versionfile.puts "#{VirtualBox::Global.global.lib.virtualbox.version.split('_')[0]}"
+ versionfile.rewind
+ begin
+ Veewee::Ssh.transfer_file("localhost",versionfile.path,".vbox_version", ssh_options)
+ rescue RuntimeError
+ puts "error transfering file, possible not enough permissions to write?"
+ exit
+ end
+ puts ""
+ versionfile.close
+ versionfile.delete
+ end
+ end #initial Transaction
- counter=1
- @definition[:postinstall_files].each do |postinstall_file|
+ counter=1
+ @definition[:postinstall_files].each do |postinstall_file|
- filename=File.join(@definition_dir,boxname,postinstall_file)
+ filename=File.join(@definition_dir,boxname,postinstall_file)
- Veewee::Ssh.when_ssh_login_works("localhost",ssh_options) do
- begin
- Veewee::Ssh.transfer_file("localhost",filename,File.basename(filename),ssh_options)
- rescue RuntimeError
- puts "error transferring file, possible not enough permissions to write?"
- exit
- end
- command=@definition[:sudo_cmd]
- newcommand=command.gsub(/%p/,"#{@definition[:ssh_password]}")
- newcommand.gsub!(/%u/,"#{@definition[:ssh_user]}")
- newcommand.gsub!(/%f/,"#{postinstall_file}")
- puts "***#{newcommand}"
- Veewee::Ssh.execute("localhost","#{newcommand}",ssh_options)
- end
+ transaction(boxname,"#{counter}-#{postinstall_file}-#{checksums[counter]}",checksums) do
- counter+=1
+ Veewee::Ssh.when_ssh_login_works("localhost",ssh_options) do
+ begin
+ Veewee::Ssh.transfer_file("localhost",filename,File.basename(filename),ssh_options)
+ rescue RuntimeError
+ puts "error transferring file, possible not enough permissions to write?"
+ exit
+ end
+ command=@definition[:sudo_cmd]
+ newcommand=command.gsub(/%p/,"#{@definition[:ssh_password]}")
+ newcommand.gsub!(/%u/,"#{@definition[:ssh_user]}")
+ newcommand.gsub!(/%f/,"#{postinstall_file}")
+ puts "***#{newcommand}"
+ Veewee::Ssh.execute("localhost","#{newcommand}",ssh_options)
+ end
- end
+ end
+ counter+=1
- puts "#{boxname} was built successfully. "
- puts ""
- puts "Now you can: "
- puts "- verify your box by running : vagrant basebox validate #{boxname}"
- puts "- export your vm to a .box file by running : vagrant basebox export #{boxname}"
+ end
+ puts "#{boxname} was built successfully. "
+ puts ""
+ puts "Now you can: "
+ puts "- verify your box by running : vagrant basebox validate #{boxname}"
+ puts "- export your vm to a .box file by running : vagrant basebox export #{boxname}"
+
end
def self.determine_vboxcmd
return "VBoxManage"
end
def self.start_vm(boxname,mode)
- vm=VirtualBox::VM.find(boxname)
- vm.start(mode)
+ vm=VirtualBox::VM.find(boxname)
+ vm.start(mode)
end
def self.load_definition(boxname)
if definition_exists?(boxname)
- definition_file=File.join(@definition_dir,boxname,"definition.rb")
- begin
- require definition_file
- rescue LoadError
- puts "Error loading definition of #{boxname}"
- exit
- end
+ definition_file=File.join(@definition_dir,boxname,"definition.rb")
+ begin
+ require definition_file
+ rescue LoadError
+ puts "Error loading definition of #{boxname}"
+ exit
+ end
else
puts "Error: definition for basebox '#{boxname}' does not exist."
list_definitions
exit
- end
+ end
end
def self.add_ssh_nat_mapping(boxname)
vm=VirtualBox::VM.find(boxname)
#Map SSH Ports
- # command => "${vboxcmd} modifyvm '${vname}' --natpf1 'guestssh,tcp,,${hostsshport},,${guestsshport}'",
+ # command => "${vboxcmd} modifyvm '${vname}' --natpf1 'guestssh,tcp,,${hostsshport},,${guestsshport}'",
port = VirtualBox::NATForwardedPort.new
port.name = "guestssh"
port.guestport = @definition[:ssh_guest_port].to_i
port.hostport = @definition[:ssh_host_port].to_i
vm.network_adapters[0].nat_driver.forwarded_ports << port
@@ -423,20 +426,20 @@
vm=VirtualBox::VM.find(boxname)
if (!vm.nil? && !(vm.powered_off?))
- puts "Shutting down vm #{boxname}"
- #We force it here, maybe vm.shutdown is cleaner
- begin
- vm.stop
- rescue VirtualBox::Exceptions::InvalidVMStateException
- puts "There was problem sending the stop command because the machine is in an Invalid state"
- puts "Please verify leftovers from a previous build in your vm folder"
- exit
- end
- sleep 3
+ puts "Shutting down vm #{boxname}"
+ #We force it here, maybe vm.shutdown is cleaner
+ begin
+ vm.stop
+ rescue VirtualBox::Exceptions::InvalidVMStateException
+ puts "There was problem sending the stop command because the machine is in an Invalid state"
+ puts "Please verify leftovers from a previous build in your vm folder"
+ exit
+ end
+ sleep 3
end
command="#{@vboxcmd} unregistervm '#{boxname}' --delete"
puts command
@@ -456,26 +459,26 @@
command="#{@vboxcmd} closemedium disk '#{d.location}' --delete"
else
command="#{@vboxcmd} closemedium disk '#{d.location}'"
end
- #command="#{@vboxcmd} closemedium disk '#{d.location}' --delete"
- puts "Deleting disk #{d.location}"
- puts "#{command}"
+ #command="#{@vboxcmd} closemedium disk '#{d.location}' --delete"
+ puts "Deleting disk #{d.location}"
+ puts "#{command}"
- Veewee::Shell.execute("#{command}")
+ Veewee::Shell.execute("#{command}")
- if File.exists?(d.location)
- puts "We tried to delete the disk file via virtualbox '#{d.location} but failed"
- puts "Removing it manually"
- FileUtils.rm(d.location)
- exit
+ if File.exists?(d.location)
+ puts "We tried to delete the disk file via virtualbox '#{d.location} but failed"
+ puts "Removing it manually"
+ FileUtils.rm(d.location)
+ exit
+ end
+ #v.3
+ #d.destroy(true)
+ break
end
- #v.3
- #d.destroy(true)
- break
- end
end
end
def self.create_vm(boxname,force=false)
@@ -493,13 +496,13 @@
vm=VirtualBox::VM.find(boxname)
if (!vm.nil? && !(vm.powered_off?))
- puts "shutting down box"
- #We force it here, maybe vm.shutdown is cleaner
- vm.stop
+ puts "shutting down box"
+ #We force it here, maybe vm.shutdown is cleaner
+ vm.stop
end
if !vm.nil?
puts "Box already exists"
#vm.stop
@@ -527,31 +530,31 @@
# Todo Check for java
# Todo check output of commands
# Check for floppy
unless @definition[:floppy_files].nil?
- require 'tmpdir'
- temp_dir=Dir.tmpdir
- @definition[:floppy_files].each do |filename|
- full_filename=full_filename=File.join(@definition_dir,boxname,filename)
- FileUtils.cp("#{full_filename}","#{temp_dir}")
- end
- javacode_dir=File.expand_path(File.join(__FILE__,'..','..','java'))
- floppy_file=File.join(@definition_dir,boxname,"virtualfloppy.vfd")
- command="java -jar #{javacode_dir}/dir2floppy.jar '#{temp_dir}' '#{floppy_file}'"
- puts "#{command}"
- Veewee::Shell.execute("#{command}")
+ require 'tmpdir'
+ temp_dir=Dir.tmpdir
+ @definition[:floppy_files].each do |filename|
+ full_filename=full_filename=File.join(@definition_dir,boxname,filename)
+ FileUtils.cp("#{full_filename}","#{temp_dir}")
+ end
+ javacode_dir=File.expand_path(File.join(__FILE__,'..','..','java'))
+ floppy_file=File.join(@definition_dir,boxname,"virtualfloppy.vfd")
+ command="java -jar #{javacode_dir}/dir2floppy.jar '#{temp_dir}' '#{floppy_file}'"
+ puts "#{command}"
+ Veewee::Shell.execute("#{command}")
- # Create floppy controller
- command="#{@vboxcmd} storagectl '#{boxname}' --name 'Floppy Controller' --add floppy"
- puts "#{command}"
- Veewee::Shell.execute("#{command}")
+ # Create floppy controller
+ command="#{@vboxcmd} storagectl '#{boxname}' --name 'Floppy Controller' --add floppy"
+ puts "#{command}"
+ Veewee::Shell.execute("#{command}")
- # Attach floppy to machine (the vfd extension is crucial to detect msdos type floppy)
- command="#{@vboxcmd} storageattach '#{boxname}' --storagectl 'Floppy Controller' --port 0 --device 0 --type fdd --medium '#{floppy_file}'"
- puts "#{command}"
- Veewee::Shell.execute("#{command}")
+ # Attach floppy to machine (the vfd extension is crucial to detect msdos type floppy)
+ command="#{@vboxcmd} storageattach '#{boxname}' --storagectl 'Floppy Controller' --port 0 --device 0 --type fdd --medium '#{floppy_file}'"
+ puts "#{command}"
+ Veewee::Shell.execute("#{command}")
end
#Exec and system stop the execution here
@@ -610,11 +613,11 @@
#newdisk.format=@definition[:disk_format]
#newdisk.logical_size=@definition[:disk_size].to_i
#newdisk.location=location
##PDB: again problems with the virtualbox GEM
- ##VirtualBox::Global.global.max_vdi_size=1000000
+ ##VirtualBox::Global.global.max_vdi_size=1000000
#newdisk.save
command="#{@vboxcmd} list systemproperties|grep '^Default machine'|cut -d ':' -f 2|sed -e 's/^[ ]*//'"
results=IO.popen("#{command}")
place=results.gets.chop
@@ -629,16 +632,16 @@
end
def self.add_ide_controller(boxname)
#unless => "${vboxcmd} showvminfo '${vname}' | grep 'IDE Controller' "
command ="#{@vboxcmd} storagectl '#{boxname}' --name 'IDE Controller' --add ide"
- Veewee::Shell.execute("#{command}")
- end
+ Veewee::Shell.execute("#{command}")
+ end
def self.add_sata_controller(boxname)
#unless => "${vboxcmd} showvminfo '${vname}' | grep 'SATA Controller' ";
- command ="#{@vboxcmd} storagectl '#{boxname}' --name 'SATA Controller' --add sata --hostiocache #{@definition[:hostiocache]}"
+ command ="#{@vboxcmd} storagectl '#{boxname}' --name 'SATA Controller' --add sata --sataportcount 1 --hostiocache #{@definition[:hostiocache]}"
Veewee::Shell.execute("#{command}")
end
def self.attach_disk(boxname)
@@ -663,11 +666,11 @@
def self.mount_isofile(boxname,isofile)
full_iso_file=File.join(@iso_dir,isofile)
puts "Mounting cdrom: #{full_iso_file}"
#command => "${vboxcmd} storageattach '${vname}' --storagectl 'IDE Controller' --type dvddrive --port 1 --device 0 --medium '${isodst}' ";
command ="#{@vboxcmd} storageattach '#{boxname}' --storagectl 'IDE Controller' --type dvddrive --port 1 --device 0 --medium '#{full_iso_file}'"
- Veewee::Shell.execute("#{command}")
+ Veewee::Shell.execute("#{command}")
end
def self.suppress_messages
@@ -729,55 +732,176 @@
end
def self.calculate_checksums(definition,boxname)
- #TODO: get rid of definitiondir and so one
- initial=definition.clone
+ #TODO: get rid of definitiondir and so one
+ initial=definition.clone
- keys=[:postinstall_files,:sudo_cmd,:postinstall_timeout]
- keys.each do |key|
- initial.delete(key)
- end
+ keys=[:postinstall_files,:sudo_cmd,:postinstall_timeout]
+ keys.each do |key|
+ initial.delete(key)
+ end
- checksums=Array.new
- checksums << Digest::MD5.hexdigest(initial.to_s)
+ checksums=Array.new
+ checksums << Digest::MD5.hexdigest(initial.to_s)
- postinstall_files=definition[:postinstall_files]
- unless postinstall_files.nil?
- for filename in postinstall_files
- begin
+ postinstall_files=definition[:postinstall_files]
+ unless postinstall_files.nil?
+ for filename in postinstall_files
+ begin
full_filename=File.join(@definition_dir,boxname,filename)
checksums << Digest::MD5.hexdigest(File.read(full_filename))
- rescue
- puts "Error reading postinstall file #{filename} - checksum"
- exit
+ rescue
+ puts "Error reading postinstall file #{filename} - checksum"
+ exit
+ end
end
end
+
+ return checksums
+
end
- return checksums
+ def self.download_progress(url,localfile)
+ pbar = nil
+ URI.parse(url).open(
+ :content_length_proc => lambda {|t|
+ if t && 0 < t
+ pbar = ProgressBar.new("Fetching file", t)
+ pbar.file_transfer_mode
+ end
+ },
+ :progress_proc => lambda {|s|
+ pbar.set s if pbar
+ }) { |src|
+ open("#{localfile}","wb") { |dst|
+ dst.write(src.read)
+ }
+ }
- end
+ end
- def self.download_progress(url,localfile)
- pbar = nil
- URI.parse(url).open(
- :content_length_proc => lambda {|t|
- if t && 0 < t
- pbar = ProgressBar.new("Fetching file", t)
- pbar.file_transfer_mode
+ def self.transaction(boxname,step_name,checksums,&block)
+
+ current_step_nr=step_name.split("-")[0].to_i
+
+ vm=VirtualBox::VM.find(boxname)
+ snapnames=Array.new
+
+ #If vm exists , look for snapshots
+ if !vm.nil?
+ start_snapshot=vm.root_snapshot
+ snapshot=start_snapshot
+ counter=0
+
+ while (snapshot!=nil)
+ #puts "#{counter}:#{snapshot.name}"
+ snapnames[counter]=snapshot.name
+ counter=counter+1
+ snapshot=snapshot.children[0]
+ end
end
- },
- :progress_proc => lambda {|s|
- pbar.set s if pbar
- }) { |src|
- open("#{localfile}","wb") { |dst|
- dst.write(src.read)
- }
- }
- end
+ #find the last snapshot matching the state
+ counter=[snapnames.length, checksums.length].min-1
+ last_good_state=counter
+ for c in 0..counter do
+ #puts "#{c}- #{snapnames[c]} - #{checksums[c]}"
+ if !snapnames[c].match("#{c}.*-#{checksums[c]}")
+ # puts "we found a bad state"
+ last_good_state=c-1
+ break
+ end
+ end
+ #puts "Last good state: #{last_good_state}"
+
+ if (current_step_nr < last_good_state)
+ #puts "fast forwarding #{step_name}"
+ return
+ end
+
+ #puts "Current step: #{current_step_nr}"
+ if (current_step_nr == last_good_state)
+ if vm.running?
+ vm.stop
+ end
+
+ #invalidate later snapshots
+ #puts "remove old snapshots"
+
+ for s in (last_good_state+1)..(snapnames.length-1)
+ puts "Removing step [#{s}] snapshot as it is no more valid"
+ snapshot=vm.find_snapshot(snapnames[s])
+ snapshot.destroy
+ #puts snapshot
+ end
+
+ vm.reload
+ puts "Loading step #{current_step_nr} snapshots as it has not changed"
+ sleep 2
+ goodsnap=vm.find_snapshot(snapnames[last_good_state])
+ goodsnap.restore
+ sleep 2
+ #TODO:Restore snapshot!!!
+ vm.start
+ sleep 4
+ puts "Starting machine"
+ end
+
+ #puts "last good state #{last_good_state}"
+
+
+ if (current_step_nr > last_good_state)
+
+ if (last_good_state==-1)
+ #no initial snapshot is found, clean machine!
+ vm=VirtualBox::VM.find(boxname)
+
+ if !vm.nil?
+ if vm.running?
+ puts "Stopping machine"
+ vm.stop
+ while vm.running?
+ sleep 1
+ end
+ end
+
+ #detaching cdroms (used to work in 3.x)
+# vm.medium_attachments.each do |m|
+# if m.type==:dvd
+# #puts "Detaching dvd"
+# m.detach
+# end
+# end
+
+ vm.reload
+ puts "We found no good state so we are destroying the previous machine+disks"
+ destroy_vm(boxname)
+ end
+
+ end
+
+ #puts "(re-)executing step #{step_name}"
+
+
+ yield
+
+ #Need to look it up again because if it was an initial load
+ vm=VirtualBox::VM.find(boxname)
+ puts "Step [#{current_step_nr}] was successfully - saving state"
+ vm.save_state
+ sleep 2 #waiting for it to be ok
+ #puts "about to snapshot #{vm}"
+ #take snapshot after successful execution
+ vm.take_snapshot(step_name,"snapshot taken by veewee")
+ sleep 2 #waiting for it to be started again
+ vm.start
+ end
+
+ #pp snapnames
+ end
+
end #End Class
end #End Module