From 61d5bb6bcea78edf71dc2f4d0af9f7b0f7fd0e90 Mon Sep 17 00:00:00 2001 From: Patrick Debois Date: Mon, 7 Feb 2011 16:03:12 +0100 Subject: [PATCH] cleaned up the output during the execution + major changes to make it work on 4.x --- Gemfile | 2 +- Gemfile.lock | 32 +++-- README => README.md | 78 +++++------- bin/veewee | 9 +- lib/vagrant_init.rb | 3 +- lib/veewee.rb | 13 -- lib/veewee/command.rb | 75 ++++++++--- lib/veewee/command2.rb | 66 ---------- lib/veewee/middleware.rb | 10 -- lib/veewee/scancode.rb | 11 +- lib/veewee/session.rb | 263 +++++++++++++++++++++++++-------------- lib/veewee/shell.rb | 4 +- lib/veewee/ssh.rb | 15 ++- lib/veewee/version.rb | 2 +- lib/veewee/web.rb | 11 +- veewee.gemspec | 1 + 16 files changed, 311 insertions(+), 284 deletions(-) rename README => README.md (66%) delete mode 100644 lib/veewee/command2.rb delete mode 100644 lib/veewee/middleware.rb diff --git a/Gemfile b/Gemfile index f5126f12..cff25c94 100644 --- a/Gemfile +++ b/Gemfile @@ -2,4 +2,4 @@ source "http://rubygems.org" gem "veewee", :path => "." -gem "vagrant", :git => "git://github.com/mitchellh/vagrant.git" +#gem "vagrant", :git => "git://github.com/mitchellh/vagrant.git" diff --git a/Gemfile.lock b/Gemfile.lock index 2a23ccd5..8d14df42 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,25 +1,11 @@ -GIT - remote: git://github.com/mitchellh/vagrant.git - revision: dc0b17583899a5cf0096f7e50fc80eb286977946 - specs: - vagrant (0.7.2.dev) - archive-tar-minitar (= 0.5.2) - erubis (~> 2.6.6) - i18n (~> 0.5.0) - json (~> 1.5.1) - mario (~> 0.0.6) - net-scp (~> 1.0.4) - net-ssh (~> 2.1.0) - thor (~> 0.14.6) - virtualbox (~> 0.8.3) - PATH remote: . specs: - veewee (0.1.0a) + veewee (0.1.1) highline (~> 1.6.1) net-ssh (~> 2.1.0) popen4 (~> 0.1.2) + progressbar thor (~> 0.14.6) vagrant (~> 0.7.0) @@ -35,7 +21,7 @@ GEM rake (>= 0.8.7) highline (1.6.1) i18n (0.5.0) - json (1.5.1) + json (1.4.6) mario (0.0.6) net-scp (1.0.4) net-ssh (>= 1.99.1) @@ -44,8 +30,19 @@ GEM popen4 (0.1.2) Platform (>= 0.4.0) open4 (>= 0.4.0) + progressbar (0.9.0) rake (0.8.7) thor (0.14.6) + vagrant (0.7.1) + archive-tar-minitar (= 0.5.2) + erubis (~> 2.6.6) + i18n (~> 0.5.0) + json (~> 1.4.6) + mario (~> 0.0.6) + net-scp (~> 1.0.4) + net-ssh (~> 2.1.0) + thor (~> 0.14.6) + virtualbox (~> 0.8.3) virtualbox (0.8.3) ffi (~> 0.6.3) @@ -53,5 +50,4 @@ PLATFORMS ruby DEPENDENCIES - vagrant! veewee! diff --git a/README b/README.md similarity index 66% rename from README rename to README.md index d8ef4182..05e3777d 100644 --- a/README +++ b/README.md @@ -1,54 +1,40 @@ -# Veewee is currently broken due to changes in Virtualbox 4.x -# We will fix them soon and move veewee to a plugin for vagrant - - -VeeWee: the tool to easily build vagrant base boxes -=================================================== +**VeeWee:** the tool to easily build vagrant base boxes Vagrant is a great tool to test new things or changes in a virtual machine(Virtualbox) using either chef or puppet. The first step is to download an existing 'base box'. I believe this scares a lot of people as they don't know who or how this box was build. Therefore lots of people end up first building their own base box to use with vagrant. Veewee tries to automate this and to share the knowledge and sources you need to create a basebox. Instead of creating custom ISO's from your favorite distribution, it leverages the 'keyboardputscancode' command of Virtualbox so send the actual 'boot prompt' keysequence to boot an existing iso. Before we can actually build the boxes, we need to take care of the minimal things to install: -- Currently this is still a very much 'it works on my machine only' code - Have Virtualbox 4.x installed -> download it from http://download.virtualbox.org/virtualbox/ -- Have ruby and rubygems working -- Have the rake gem installed -> gem install rake - -ALPHA CODE: -> you're on your own.... -### WILL UPDATE SOON #### +ALPHA CODE: -> you're on your own.... -1)Installation: (from source) -=========================== +## Installation: (from source) +**from source ** $ git clone https://github.com/jedi4ever/veewee.git $ cd veewee $ gem install bundler -$ bundle install - -Installation: (as a gem) -======================== -coming soon - -List all templates -=================== -$ rake templates -the following templates are available: -use rake define['','CentOS-4.8-i386'] -use rake define['','CentOS-5.5-i386'] -use rake define['','ubuntu-10.04.1-server-i386'] -use rake define['','ubuntu-10.10-server-i386'] - -3) Define a new box (ex. Ubuntu 10.10 server i386) - this is essentially making a copy based on the templates provided above. -$ rake define['myubuntubox','ubuntu-10.10-server-i386'] +$ bundle install + +**as a gem** +$ gem install veewee + + +## List all templates +$ vagrant basebox templates + +## Define a new box (ex. Ubuntu 10.10 server i386) + +this is essentially making a copy based on the templates provided above. +$ vagrant basebox define 'myubuntubox' 'ubuntu-10.10-server-i386' template successfully copied --> This copies over the files in templates/ubuntu-10.10-server-i386 to definition/myubuntubox +-> This copies over the templates/ubuntu-10.10-server-i386 to definition/myubuntubox $ ls definitions/myubuntubox definition.rb postinstall.sh postinstall2.sh preseed.cfg -4) Optionally modify the definition.rb , postinstall.sh or preseed.cfg +## Optionally modify the definition.rb , postinstall.sh or preseed.cfg Veewee::Session.declare( { :cpu_count => '1', :memory_size=> '256', :disk_size => '10140', :disk_format => 'VDI',:disk_size => '10240' , @@ -78,13 +64,14 @@ Veewee::Session.declare( { If you need to change values in the templates, be sure to run the rake undefine, the rake define again to copy the changes across. -5) Put your isofile inside the $VEEWEE/iso directory or if you don't run -$ rake build['myubuntubox] +## Put your isofile inside the $VEEWEE/iso directory or if you don't run +$ vagrant basebox build 'myubuntubox' --> This will show you the iso to download +-> the build assumes your iso files are in 'currentdir'/iso +-> if it can not find it will suggest to download the iso for you 6) Build the new box: -$ rake build['myubuntubox] +$ vagrant basebox build 'myubuntubox' -> This will create a machine + disk according to the definition.rb -> Note: :os_type_id = The internal Name Virtualbox uses for that Distribution @@ -95,15 +82,18 @@ $ rake build['myubuntubox] -> Wait for ssh login to work with :ssh_user , :ssh_password -> Sudo execute the :postinstall_files -7) Export the box into the boxes directory -$ rake export['myubuntubox'] +## Export the vm to a .box file +$ vagrant basebox export 'myubuntubox' + +this is actually calling - vagrant package --base 'myubuntubox' --output 'boxes/myubuntubox.box' -vagrant package --base 'myubuntubox' --output 'boxes/myubuntubox.box' -vagrant box add 'myubuntubox' 'boxes/myubuntubox.box' +this will result in a myubuntubox.box --> This will show you the vagrant command to export and to add it your vagrant boxset +## Add the box as one of your boxes +vagrant box add 'myubuntubox' 'myubuntubox.box' -8) Start vagrant init in another window (as we have set the Virtualbox env to tmp before) +## Use it in vagrant +Start vagrant init in another window (as we have set the Virtualbox env to tmp before) $ To import it into vagrant type: To use it: @@ -111,7 +101,7 @@ vagrant init 'myubuntubox' vagrant up vagrant ssh -9) If you have a setup working, share your 'definition' with me. That would be fun! +## If you have a setup working, share your 'definition' with me. That would be fun! IDEAS: - Now you integrate this with your CI build to create a daily basebox diff --git a/bin/veewee b/bin/veewee index 2b298467..74275e4a 100755 --- a/bin/veewee +++ b/bin/veewee @@ -30,6 +30,8 @@ Dir.glob(File.join(lib_dir, '**','*.rb')).each {|f| Veewee::Session.setenv({:veewee_dir => veewee_dir, :definition_dir => definition_dir, :template_dir => template_dir, :iso_dir => iso_dir, :box_dir => box_dir, :tmp_dir => tmp_dir}) + + class VeeweeCLI < Thor desc "init [NAME] [TEMPLATE]", "initializes a box from a template" @@ -67,10 +69,11 @@ class VeeweeCLI < Thor end + + version=VirtualBox.version if (version.match(/^4./)) - VeeweeCLI.start + VeeweeCLI.start else - puts "veewee only supports VirtualBox 4.x" + puts "veewee only supports VirtualBox 4.x" end - diff --git a/lib/vagrant_init.rb b/lib/vagrant_init.rb index 6f2eb145..e7c5d5ae 100644 --- a/lib/vagrant_init.rb +++ b/lib/vagrant_init.rb @@ -1,2 +1 @@ -require 'veewee' -puts "here we are" +require 'veewee' \ No newline at end of file diff --git a/lib/veewee.rb b/lib/veewee.rb index f01f2e74..a7f2fb97 100644 --- a/lib/veewee.rb +++ b/lib/veewee.rb @@ -1,15 +1,2 @@ require 'vagrant' -#require 'veewee/config' require 'veewee/command' -#require 'veewee/middleware' - - -#basebox = Vagrant::Action::Builder.new do - #use BaseBoxMiddleware -#end - -#Vagrant::Action.register :basebox, basebox - -# Add our custom translations to the load path -I18n.load_path << File.expand_path("../../locales/en.yml", __FILE__) - diff --git a/lib/veewee/command.rb b/lib/veewee/command.rb index 95540dcc..dbabcc73 100644 --- a/lib/veewee/command.rb +++ b/lib/veewee/command.rb @@ -1,23 +1,58 @@ +require 'veewee/session' + +#Load Veewee::Session libraries +lib_dir= File.expand_path(File.join(File.dirname(__FILE__),"..","..", "lib")) +Dir.glob(File.join(lib_dir, '**','*.rb')).each {|f| require f } + +#Setup some base variables to use +template_dir=File.expand_path(File.join(lib_dir,"..", "templates")) + +veewee_dir="." +definition_dir= File.expand_path(File.join(veewee_dir, "definitions")) +tmp_dir=File.expand_path(File.join(veewee_dir, "tmp")) +iso_dir=File.expand_path(File.join(veewee_dir, "iso")) +box_dir=File.expand_path(File.join(veewee_dir, "boxes")) + +#Initialize +Veewee::Session.setenv({:veewee_dir => veewee_dir, :definition_dir => definition_dir, + :template_dir => template_dir, :iso_dir => iso_dir, :box_dir => box_dir, :tmp_dir => tmp_dir}) + module Veewee - class Command < Vagrant::Command::Base - register "bla", "Run a rake task inside the VM environment" - #argument :rake_command, :type => :array, :required => false, :desc => "The command to run on the VM via Rake" - #class_option :cwd, :type => :string, :default => nil - - # Executes the given rake command on the VMs that are represented - # by this environment. - def execute - command = (rake_command || []).join(" ") - target_vms.each { |vm| execute_on_vm(vm, command) } - end - - protected - - # Executes a command on a specific VM. - def execute_on_vm(vm, command) - vm.env.actions.run(:rake, - "rake.command" => command, - "rake.cwd" => options[:cwd]) - end +class Command < Vagrant::Command::GroupBase + register "basebox","Commands to manage baseboxes" + + desc "templates", "List the currently available box templates" + def templates + Veewee::Session.list_templates + end + + desc "define BOXNAME TEMPLATE", "Define a new box starting from a template" + method_option :force,:type => :boolean , :default => false, :aliases => "-f", :desc => "overwrite the definition" + def define(boxname, template) + Veewee::Session.define(boxname,template,options) end + + desc "build BOXNAME", "Build the box BOXNAME" + method_option :force,:type => :boolean , :default => false, :aliases => "-f", :desc => "overwrite the basebox" + def build(boxname) + Veewee::Session.build(boxname,options) + end + + desc "ostypes", "List the available Operating System types" + def ostypes + Veewee::Session.list_ostypes + end + + desc "destroy", "Destroy the virtualmachine of a basebox" + def destroy(boxname) + puts Veewee::Session.destroy_vm(boxname) + end + + desc "list", "Lists all defined boxes" + def list + Veewee::Session.list_definitions + end + end + +end \ No newline at end of file diff --git a/lib/veewee/command2.rb b/lib/veewee/command2.rb deleted file mode 100644 index a8ae1cb4..00000000 --- a/lib/veewee/command2.rb +++ /dev/null @@ -1,66 +0,0 @@ -require 'veewee/session' - -#Load Veewee::Session libraries -lib_dir= File.expand_path(File.join(File.dirname(__FILE__),"..","..", "lib")) -Dir.glob(File.join(lib_dir, '**','*.rb')).each {|f| require f } - -#Setup some base variables to use -template_dir=File.expand_path(File.join(lib_dir,"..", "templates")) - -veewee_dir="." -definition_dir= File.expand_path(File.join(veewee_dir, "definitions")) -tmp_dir=File.expand_path(File.join(veewee_dir, "tmp")) -iso_dir=File.expand_path(File.join(veewee_dir, "iso")) -box_dir=File.expand_path(File.join(veewee_dir, "boxes")) - -#Initialize -Veewee::Session.setenv({:veewee_dir => veewee_dir, :definition_dir => definition_dir, - :template_dir => template_dir, :iso_dir => iso_dir, :box_dir => box_dir, :tmp_dir => tmp_dir}) - -puts "we get here" - -class Command22 < Vagrant::Command::GroupBase - register "basebox","Commands to manage baseboxes" - - desc "templates", "List the currently available box templates" - def templates - Veewee::Session.list_templates - end - - desc "define BOXNAME TEMPLATE", "Define a new box starting from a template" - def define(boxname, template) - puts "define a new box #{boxname}, starting from template #{template}" - Veewee::Session.define(boxname,template) - end - - desc "build BOXNAME", "Build the box BOXNAME" - def build(boxname) - puts "Building box #{boxname}" - Veewee::Session.build(boxname) - end - - desc "ostypes", "List the available Operating System types" - def ostypes - puts "Operating System types:" - Veewee::Session.list_ostypes - end - - desc "clean", "Clean all unfinished builds" - def clean - puts "Cleaning all unfinished builds" - end - -end - - -class SayHelloCommand < Vagrant::Command::Base - register "hello", "Says hello then goodbye" - - def hello - puts "HELLO!" - end - - def goodbye - puts "GOODBYE!" - end -end diff --git a/lib/veewee/middleware.rb b/lib/veewee/middleware.rb deleted file mode 100644 index f96b9864..00000000 --- a/lib/veewee/middleware.rb +++ /dev/null @@ -1,10 +0,0 @@ -class BaseBoxMiddleware - def initialize(app, env) - @app = app - end - - def call(env) - env["ui"].info "Hello!" - @app.call(env) - end -end \ No newline at end of file diff --git a/lib/veewee/scancode.rb b/lib/veewee/scancode.rb index f2dd47bd..b92b47b9 100644 --- a/lib/veewee/scancode.rb +++ b/lib/veewee/scancode.rb @@ -2,11 +2,16 @@ module Veewee class Scancode def self.send_sequence(vboxcmd,vname,sequence) - + puts + counter=0 sequence.each { |s| + counter=counter+1 + s.gsub!(/%IP%/,Veewee::Session.local_ip); s.gsub!(/%PORT%/,'7122'); s.gsub!(/%NAME%/, vname); + puts "Typing:[#{counter}]: "+s + keycodes=string_to_keycode(s) # VBox seems to have issues with sending the scancodes as one big @@ -21,13 +26,15 @@ def self.send_sequence(vboxcmd,vname,sequence) sleep 1 } + puts "Done typing." + puts end def self.send_keycode(vboxcmd,vname,keycode) command= "#{vboxcmd} controlvm '#{vname}' keyboardputscancode #{keycode}" #puts "#{command}" - IO.popen("#{command}") { |f| print '.' } + IO.popen("#{command}") { |f| print '' } end def self.string_to_keycode(thestring) diff --git a/lib/veewee/session.rb b/lib/veewee/session.rb index 64e6792c..86610cf9 100644 --- a/lib/veewee/session.rb +++ b/lib/veewee/session.rb @@ -2,6 +2,10 @@ require 'socket' require 'net/scp' require 'pp' +require 'open-uri' +require 'progressbar' +require 'highline/import' +require 'tempfile' module Veewee @@ -41,25 +45,43 @@ def self.declare(options) end - def self.define(boxname,template_name) + def self.define(boxname,template_name,options = {}) #Check if template_name exists - #puts @veewee_dir + + options = { "force" => false, "format" => "vagrant" }.merge(options) + if File.directory?(File.join(@template_dir,template_name)) else - puts "this template can not be found, use vagrant box templates to list all templates" + puts "This template can not be found, use vagrant basebox templates to list all templates" + exit end if !File.exists?(@definition_dir) FileUtils.mkdir(@definition_dir) end + if File.directory?(File.join(@definition_dir,boxname)) - puts "this definition already exists" + if !options["force"] + puts "The definition for #{boxname} already exists. Use --force to overwrite" + exit + end else FileUtils.mkdir(File.join(@definition_dir,boxname)) - FileUtils.cp_r(File.join(@template_dir,template_name,'.'),File.join(@definition_dir,boxname)) - puts "template succesfully copied" end + FileUtils.cp_r(File.join(@template_dir,template_name,'.'),File.join(@definition_dir,boxname)) + puts "The basebox '#{boxname}' has been succesfully 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 + end + + def self.definition_exists?(boxname) if File.directory?(File.join(@definition_dir,boxname)) @@ -85,15 +107,20 @@ def self.undefine(boxname) end end - def self.list_templates - puts "the following templates are available:" + def self.list_templates( options = { :format => 'vagrant'}) + puts "The following templates are available:" subdirs=Dir.glob("#{@template_dir}/*") subdirs.each do |sub| if File.directory?("#{sub}") definition=Dir.glob("#{sub}/definition.rb") if definition.length!=0 name=sub.sub(/#{@template_dir}\//,'') - puts "vagrant box init '' '#{name}'" + if (options[:format]=='vagrant') + puts "vagrant basebox define '' '#{name}'" + end + if (options[:format]=='veewee') + puts "veewee define '' '#{name}'" + end end end end @@ -111,9 +138,10 @@ def self.clean puts "Not yet implemented" end - def self.verify_iso(filename) + def self.verify_iso(filename,autodownload = false) if File.exists?(File.join(@iso_dir,filename)) - puts "isofile #{filename} is available" + puts + puts "Verifying the isofile #{filename} is ok." else full_path=File.join(@iso_dir,filename) path1=Pathname.new(full_path) @@ -121,15 +149,23 @@ def self.verify_iso(filename) rel_path=path1.relative_path_from(path2).to_s puts - puts "Isofile is not found. The definition suggested the following URL to download:" - puts "-url: #{@definition[:iso_src]}" - puts "-md5: #{@definition[:iso_md5]}" + puts "The isofile is not found. The definition provided the following information:" + puts "- Download url: #{@definition[:iso_src]}" + puts "- Md5 Checksum: #{@definition[:iso_md5]}" puts "" - puts "type:" - 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" + 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 @@ -145,7 +181,10 @@ def self.remove_box(boxname) puts "Not yet implemented" end - def self.build(boxname) + def self.build(boxname,options) + + options = { "force" => false, "format" => "vagrant" }.merge(options) + #Now we have to load the definition (reads definition.rb) load_definition(boxname) @@ -160,9 +199,13 @@ def self.build(boxname) verify_iso(@definition[:iso_file]) + if (options["force"]==false) + else + puts "Forcing build by destroying #{boxname} machine" + destroy_vm(boxname) + end + checksums=calculate_checksums(@definition,boxname) - - transaction(boxname,"0-initial-#{checksums[0]}",checksums) do @@ -187,11 +230,12 @@ def self.build(boxname) #waiting for it to boot + puts "Waiting for the machine to boot" sleep @definition[:boot_wait].to_i - puts "sending keys" Veewee::Scancode.send_sequence("#{@vboxcmd}","#{boxname}",@definition[:boot_cmd_sequence]) + puts "Starting a webserver on port #{@definition[:kickstart_port]}" #:kickstart_port => "7122", :kickstart_ip => self.local_ip, :kickstart_timeout => 1000,:kickstart_file => "preseed.cfg", Veewee::Web.wait_for_request(@definition[:kickstart_file],{:port => @definition[:kickstart_port], :host => @definition[:kickstart_ip], :timeout => @definition[:kickstart_timeout], @@ -199,15 +243,16 @@ def self.build(boxname) Veewee::Ssh.when_ssh_login_works("localhost",ssh_options) do #Transfer version of Virtualbox to $HOME/.vbox_version - versionfile=File.join(@tmp_dir,".vbox_version") - File.open(versionfile, 'w') {|f| f.write("#{VirtualBox::Global.global.lib.virtualbox.version}") } - Veewee::Ssh.transfer_file("localhost",versionfile,ssh_options) + versionfile=Tempfile.open("vbox.version") + versionfile.puts "#{VirtualBox::Global.global.lib.virtualbox.version}" + versionfile.rewind + Veewee::Ssh.transfer_file("localhost",versionfile.path,".vbox_version", ssh_options) + versionfile.close + versionfile.delete end end #initial Transaction - - - + counter=1 @definition[:postinstall_files].each do |postinstall_file| @@ -270,7 +315,53 @@ def self.add_ssh_nat_mapping(boxname) vm.save end - def self.create_vm(boxname) + def self.destroy_vm(boxname) + #:destroy_medium => :delete, will delete machine + all media attachments + #vm.destroy(:destroy_medium => :delete) + ##vm.destroy(:destroy_image => true) + + #VBoxManage unregistervm "test-machine" --delete + #because the destroy does remove the .vbox file on 4.0.x + #PDB + #vm.destroy() + + 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 + vm.stop + end + sleep 3 + + command="#{@vboxcmd} unregistervm '#{boxname}' --delete" + + puts "Deleting vm #{boxname}" + + #Exec and system stop the execution here + Veewee::Shell.execute("#{command}") + sleep 1 + + #if the disk was not attached when the machine was destroyed we also need to delete the disk + location=boxname+"."+@definition[:disk_format].downcase + found=false + VirtualBox::HardDrive.all.each do |d| + if !d.location.match(/#{location}/).nil? + + command="#{@vboxcmd} closemedium disk '#{d.location}' --delete" + puts "Deleting disk #{d.location}" + Veewee::Shell.execute("#{command}") + #v.3 + #d.destroy(true) + break + end + end + + + + end + + def self.create_vm(boxname,force=false) #Verifying the os.id with the :os_type_id specified matchfound=false @@ -293,8 +384,8 @@ def self.create_vm(boxname) vm.stop end - if !vm.nil? - puts "box already exists" + if !vm.nil? + puts "Box already exists" #vm.stop #vm.destroy else @@ -302,11 +393,9 @@ def self.create_vm(boxname) #Box does not exist, we can start to create it command="#{@vboxcmd} createvm --name '#{boxname}' --ostype '#{@definition[:os_type_id]}' --register" - puts command #Exec and system stop the execution here Veewee::Shell.execute("#{command}") - sleep 3 end @@ -322,7 +411,8 @@ def self.create_vm(boxname) vm.os_type_id=@definition[:os_type_id] vm.cpu_count=@definition[:cpu_count].to_i vm.name=boxname - + + puts "Creating vm #{vm.name} : #{vm.memory_size}M - #{vm.cpu_count} CPU - #{vm.os_type_id}" #setting bootorder vm.boot_order[0]=:hard_disk vm.boot_order[1]=:dvd @@ -348,7 +438,7 @@ def self.create_disk(boxname) end if !found - puts "creating new harddrive" + puts "Creating new harddrive of size #{@definition[:disk_size].to_i} " #newdisk=VirtualBox::HardDrive.new #newdisk.format=@definition[:disk_format] @@ -364,8 +454,7 @@ def self.create_disk(boxname) place=results.gets.chop results.close - puts "#{command}" - command ="#{@vboxcmd} createhd --filename '#{place}/#{boxname}/#{boxname}.#{@definition[:disk_format]}' --size '#{@definition[:disk_size].to_i}' --format #{@definition[:disk_format]}" + command ="#{@vboxcmd} createhd --filename '#{place}/#{boxname}/#{boxname}.#{@definition[:disk_format]}' --size '#{@definition[:disk_size].to_i}' --format #{@definition[:disk_format]} > /dev/null" Veewee::Shell.execute("#{command}") end @@ -394,20 +483,17 @@ def self.attach_disk(boxname) results.close location="#{place}/#{boxname}/"+location - - puts "location=#{location}" - + puts "Attaching disk: #{location}" #command => "${vboxcmd} storageattach '${vname}' --storagectl 'SATA Controller' --port 0 --device 0 --type hdd --medium '${vname}.vdi'", command ="#{@vboxcmd} storageattach '#{boxname}' --storagectl 'SATA Controller' --port 0 --device 0 --type hdd --medium '#{location}'" - puts "#{command}" Veewee::Shell.execute("#{command}") end def self.mount_isofile(boxname,isofile) full_iso_file=File.join(@iso_dir,isofile) - puts "#{full_iso_file}" + 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}") @@ -443,10 +529,7 @@ def self.list_ostypes puts "Available os types:" VirtualBox::Global.global.lib.virtualbox.guest_os_types.collect { |os| puts "#{os.id}: #{os.description}" - } - - puts - + } end @@ -477,11 +560,28 @@ def self.calculate_checksums(definition,boxname) end end - pp checksums return checksums 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 + end + }, + :progress_proc => lambda {|s| + pbar.set s if pbar + }) { |src| + open("#{localfile}","wb") { |dst| + dst.write(src.read) + } + } + + end def self.transaction(boxname,step_name,checksums,&block) @@ -504,8 +604,6 @@ def self.transaction(boxname,step_name,checksums,&block) end end - pp snapnames - #find the last snapshot matching the state counter=[snapnames.length, checksums.length].min-1 last_good_state=counter @@ -517,14 +615,14 @@ def self.transaction(boxname,step_name,checksums,&block) break end end - puts "Last good state: #{last_good_state}" + #puts "Last good state: #{last_good_state}" if (current_step_nr < last_good_state) - puts "fast forwarding #{step_name}" + #puts "fast forwarding #{step_name}" return end - puts "Current step: #{current_step_nr}" + #puts "Current step: #{current_step_nr}" if (current_step_nr == last_good_state) if vm.running? vm.stop @@ -534,14 +632,14 @@ def self.transaction(boxname,step_name,checksums,&block) #puts "remove old snapshots" for s in (last_good_state+1)..(snapnames.length-1) - puts "removing snapname #{snapnames[s]}" + 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 "action load #{step_name}" + puts "Loading step #{current_step_nr} snapshots as it has not changed" sleep 2 goodsnap=vm.find_snapshot(snapnames[last_good_state]) goodsnap.restore @@ -551,7 +649,7 @@ def self.transaction(boxname,step_name,checksums,&block) end - puts "last good state #{last_good_state}" + #puts "last good state #{last_good_state}" if (current_step_nr > last_good_state) @@ -562,66 +660,41 @@ def self.transaction(boxname,step_name,checksums,&block) if !vm.nil? if vm.running? - puts "stopping machine" + puts "Stopping machine" vm.stop while vm.running? sleep 1 end end - #detaching cdroms - vm.medium_attachments.each do |m| - if m.type==:dvd - puts "detaching dvd" - m.detach - 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 "destroying machine+disks" - #:destroy_medium => :delete, will delete machine + all media attachments - #vm.destroy(:destroy_medium => :delete) - ##vm.destroy(:destroy_image => true) - - #VBoxManage unregistervm "test-machine" --delete - #because the destroy does remove the .vbox file on 4.0.x - #PDB - #vm.destroy() - - command="#{@vboxcmd} unregistervm '#{boxname}' --delete" - puts command - - #Exec and system stop the execution here - Veewee::Shell.execute("#{command}") - - #if the disk was not attached when the machine was destroyed we also need to delete the disk - location=boxname+"."+@definition[:disk_format].downcase - found=false - VirtualBox::HardDrive.all.each do |d| - if !d.location.match(/#{location}/).nil? - d.destroy(true) - break - end - end + 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}" + #puts "(re-)executing step #{step_name}" yield - puts "seeking #{boxname}" + #Need to look it up again because if it was an initial load vm=VirtualBox::VM.find(boxname) - puts "saving state" + puts "Step [#{current_step_nr}] was succesfull - saving state" vm.save_state - puts "waiting for 2 secs" sleep 2 #waiting for it to be ok - puts "about to snapshot #{vm}" + #puts "about to snapshot #{vm}" #take snapshot after succesful execution vm.take_snapshot(step_name,"snapshot taken by veewee") - puts "wait 2 secs before starting" sleep 2 #waiting for it to be started again vm.start end diff --git a/lib/veewee/shell.rb b/lib/veewee/shell.rb index b87390dc..38830d8b 100644 --- a/lib/veewee/shell.rb +++ b/lib/veewee/shell.rb @@ -15,7 +15,9 @@ def self.execute(command, options = {} ) begin PTY.spawn( command ) do |r, w, pid| begin - r.each { |line| print line;} + r.each { } + #r.each { |line| print line;} + rescue Errno::EIO end end diff --git a/lib/veewee/ssh.rb b/lib/veewee/ssh.rb index b8eaef13..2fe9facf 100644 --- a/lib/veewee/ssh.rb +++ b/lib/veewee/ssh.rb @@ -5,10 +5,11 @@ def self.when_ssh_login_works(ip="localhost", options = { } , &block) defaults={ :port => '22', :timeout => 200 , :user => 'vagrant', :password => 'vagrant'} - puts "checking if login works ssh => #{options[:port]}" - options=defaults.merge(options) + puts + puts "Trying ssh login with user #{options[:user]} to sshd on port => #{options[:port]}" + begin Timeout::timeout(options[:timeout]) do connected=false @@ -33,11 +34,13 @@ def self.when_ssh_login_works(ip="localhost", options = { } , &block) end - def self.transfer_file(host,filename,options) + def self.transfer_file(host,filename,destination = '.' , options) Net::SSH.start( host,options[:user],options ) do |ssh| - puts "Transferring #{filename} " - ssh.scp.upload!( filename, '.' ) do |ch, name, sent, total| - print "\r#{filename}: #{(sent.to_f * 100 / total.to_f).to_i}%" + puts "Transferring #{filename} to #{destination} " + ssh.scp.upload!( filename, destination ) do |ch, name, sent, total| + # print "\r#{destination}: #{(sent.to_f * 100 / total.to_f).to_i}%" + print "." + end end puts diff --git a/lib/veewee/version.rb b/lib/veewee/version.rb index fd30b8be..79f1082b 100644 --- a/lib/veewee/version.rb +++ b/lib/veewee/version.rb @@ -1,3 +1,3 @@ module Veewee - VERSION = "0.1.0a" + VERSION = "0.1.1" end diff --git a/lib/veewee/web.rb b/lib/veewee/web.rb index 795529ea..b9dd4c93 100644 --- a/lib/veewee/web.rb +++ b/lib/veewee/web.rb @@ -14,7 +14,7 @@ def initialize(server,localfile) def do_GET(request,response) response['Content-Type']='text/plain' response.status = 200 - + puts "Serving file #{@localfile}" displayfile=File.open(@localfile,'r') content=displayfile.read() response.body=content @@ -26,12 +26,19 @@ def do_GET(request,response) def self.wait_for_request(filename,options={:timeout => 10, :web_dir => "", :port => 7125}) + webrick_logger=WEBrick::Log.new("/dev/null", WEBrick::Log::INFO) + web_dir=options[:web_dir] filename=filename - s= HTTPServer.new(:Port => options[:port]) + s= HTTPServer.new( + :Port => options[:port], + :Logger => webrick_logger, + :AccessLog => webrick_logger + ) s.mount("/#{filename}", FileServlet,File.join(web_dir,filename)) trap("INT"){ s.shutdown + puts "Stopping webserver" exit } s.start diff --git a/veewee.gemspec b/veewee.gemspec index f6513f39..3c668a22 100644 --- a/veewee.gemspec +++ b/veewee.gemspec @@ -19,6 +19,7 @@ Gem::Specification.new do |s| s.add_dependency "popen4", "~> 0.1.2" s.add_dependency "thor", "~> 0.14.6" s.add_dependency "highline", "~> 1.6.1" + s.add_dependency "progressbar" s.add_development_dependency "bundler", ">= 1.0.0"