move_hd during hobo up
This commit is contained in:
parent
7fd4ee0160
commit
3a3fbb44c7
|
@ -8,7 +8,7 @@ require 'logger'
|
|||
require 'virtualbox'
|
||||
require 'net/ssh'
|
||||
require 'ping'
|
||||
require 'hobo/error'
|
||||
require 'hobo/util'
|
||||
require 'hobo/config'
|
||||
require 'hobo/env'
|
||||
require 'hobo/ssh'
|
||||
|
|
|
@ -7,7 +7,7 @@ module Hobo
|
|||
@config = nil
|
||||
@config_runners = []
|
||||
|
||||
class <<self
|
||||
class << self
|
||||
def config
|
||||
@config ||= Config::Top.new
|
||||
end
|
||||
|
@ -48,6 +48,7 @@ module Hobo
|
|||
attr_accessor :base_mac
|
||||
attr_accessor :project_directory
|
||||
attr_reader :forwarded_ports
|
||||
attr_accessor :hd_location
|
||||
|
||||
def initialize
|
||||
@forwarded_ports = {}
|
||||
|
@ -60,6 +61,11 @@ module Hobo
|
|||
:protocol => protocol
|
||||
}
|
||||
end
|
||||
|
||||
def hd_location=(val)
|
||||
raise Exception.new "disk_storage must be set to a directory" unless File.directory?(val)
|
||||
@hd_location=val
|
||||
end
|
||||
end
|
||||
|
||||
class Top < Base
|
||||
|
|
|
@ -8,7 +8,7 @@ module Hobo
|
|||
@@persisted_vm = nil
|
||||
@@root_path = nil
|
||||
|
||||
extend Hobo::Error
|
||||
extend Hobo::Util
|
||||
|
||||
class << self
|
||||
def persisted_vm; @@persisted_vm; end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module Hobo
|
||||
module Error
|
||||
module Util
|
||||
def error_and_exit(error)
|
||||
puts <<-error
|
||||
=====================================================================
|
||||
|
@ -10,5 +10,10 @@ Hobo experienced an error!
|
|||
error
|
||||
exit
|
||||
end
|
||||
|
||||
def logger
|
||||
HOBO_LOGGER
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
module Hobo
|
||||
class VM
|
||||
HD_EXT_DEFAULT = 'VMDK'
|
||||
attr_reader :vm
|
||||
|
||||
extend Hobo::Error
|
||||
extend Hobo::Util
|
||||
include Hobo::Util
|
||||
|
||||
class << self
|
||||
# Bring up the virtual machine. Imports the base image and
|
||||
|
@ -28,9 +30,10 @@ module Hobo
|
|||
def suspend
|
||||
Env.require_persisted_vm
|
||||
error_and_exit(<<-error) if Env.persisted_vm.saved?
|
||||
The hobo virtual environment you are trying to resume is already in a
|
||||
The hobo virtual environment you are trying to suspend is already in a
|
||||
suspended state.
|
||||
error
|
||||
logger.info "Saving VM state..."
|
||||
Env.persisted_vm.save_state(true)
|
||||
end
|
||||
|
||||
|
@ -59,6 +62,7 @@ error
|
|||
|
||||
def create
|
||||
import
|
||||
move_hd if Hobo.config[:vm][:hd_location]
|
||||
persist
|
||||
setup_mac_address
|
||||
forward_ports
|
||||
|
@ -69,26 +73,46 @@ error
|
|||
|
||||
def destroy
|
||||
if @vm.running?
|
||||
HOBO_LOGGER.info "VM is running. Forcing immediate shutdown..."
|
||||
logger.info "VM is running. Forcing immediate shutdown..."
|
||||
@vm.stop(true)
|
||||
end
|
||||
|
||||
HOBO_LOGGER.info "Destroying VM and associated drives..."
|
||||
logger.info "Destroying VM and associated drives..."
|
||||
@vm.destroy(:destroy_image => true)
|
||||
end
|
||||
|
||||
def move_hd
|
||||
error_and_exit(<<-error) unless @vm.powered_off?
|
||||
The virtual machine must be powered off to move its disk.
|
||||
error
|
||||
|
||||
old_image = hd.image.dup
|
||||
new_image_file = Hobo.config[:vm][:hd_location] + old_image.filename
|
||||
|
||||
logger.info "Cloning current VM Disk to new location (#{ new_image_file })..."
|
||||
# TODO image extension default?
|
||||
new_image = hd.image.clone(new_image_file , HD_EXT_DEFAULT, true)
|
||||
hd.image = new_image
|
||||
|
||||
logger.info "Attaching new disk to VM ..."
|
||||
@vm.save
|
||||
|
||||
logger.info "Destroying old VM Disk (#{ old_image.filename })..."
|
||||
old_image.destroy(true)
|
||||
end
|
||||
|
||||
def import
|
||||
HOBO_LOGGER.info "Importing base VM (#{Hobo.config[:vm][:base]})..."
|
||||
logger.info "Importing base VM (#{Hobo.config[:vm][:base]})..."
|
||||
@vm = VirtualBox::VM.import(File.expand_path(Hobo.config[:vm][:base]))
|
||||
end
|
||||
|
||||
def persist
|
||||
HOBO_LOGGER.info "Persisting the VM UUID (#{@vm.uuid})..."
|
||||
logger.info "Persisting the VM UUID (#{@vm.uuid})..."
|
||||
Env.persist_vm(@vm)
|
||||
end
|
||||
|
||||
def setup_mac_address
|
||||
HOBO_LOGGER.info "Matching MAC addresses..."
|
||||
logger.info "Matching MAC addresses..."
|
||||
@vm.nics.first.macaddress = Hobo.config[:vm][:base_mac]
|
||||
@vm.save(true)
|
||||
end
|
||||
|
@ -109,7 +133,7 @@ error
|
|||
end
|
||||
|
||||
def setup_shared_folder
|
||||
HOBO_LOGGER.info "Creating shared folders..."
|
||||
logger.info "Creating shared folders..."
|
||||
folder = VirtualBox::SharedFolder.new
|
||||
folder.name = "hobo-root-path"
|
||||
folder.hostpath = Env.root_path
|
||||
|
@ -126,28 +150,31 @@ error
|
|||
end
|
||||
|
||||
def start
|
||||
HOBO_LOGGER.info "Booting VM..."
|
||||
logger.info "Booting VM..."
|
||||
@vm.start(:headless, true)
|
||||
|
||||
# Now we have to wait for the boot to be successful
|
||||
HOBO_LOGGER.info "Waiting for VM to boot..."
|
||||
logger.info "Waiting for VM to boot..."
|
||||
|
||||
Hobo.config[:ssh][:max_tries].to_i.times do |i|
|
||||
sleep 5 unless ENV['HOBO_ENV'] == 'test'
|
||||
HOBO_LOGGER.info "Trying to connect (attempt ##{i+1} of #{Hobo.config[:ssh][:max_tries]})..."
|
||||
logger.info "Trying to connect (attempt ##{i+1} of #{Hobo.config[:ssh][:max_tries]})..."
|
||||
|
||||
if Hobo::SSH.up?
|
||||
HOBO_LOGGER.info "VM booted and ready for use!"
|
||||
logger.info "VM booted and ready for use!"
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
HOBO_LOGGER.info "Failed to connect to VM! Failed to boot?"
|
||||
logger.info "Failed to connect to VM! Failed to boot?"
|
||||
false
|
||||
end
|
||||
|
||||
def saved?; @vm.saved? end
|
||||
|
||||
def save_state(errs); @vm.save_state(errs) end
|
||||
|
||||
# TODO need a better way to which controller is the hd
|
||||
def hd; @vm.storage_controllers.first.devices.first end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,10 +11,9 @@ if { $port != "" } {
|
|||
set port_option ""
|
||||
}
|
||||
|
||||
spawn ssh $port_option $uname@$host
|
||||
spawn ssh $port_option -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $uname@$host
|
||||
|
||||
expect "*password: " {
|
||||
sleep 1
|
||||
send "$password\r"
|
||||
} timeout {
|
||||
send_user "Error connecting"
|
||||
|
|
|
@ -235,5 +235,41 @@ class VMTest < Test::Unit::TestCase
|
|||
Hobo::Env.persisted_vm.expects(:start).once.returns(true)
|
||||
end
|
||||
end
|
||||
|
||||
context "creating a new vm with a specified disk storage location" do
|
||||
|
||||
should "error and exit of the vm is not powered off" do
|
||||
# Exit does not prevent method from proceeding in test, so we must set expectations
|
||||
vm = move_hd_expectations
|
||||
@mock_vm.expects(:powered_off?).returns(false)
|
||||
vm.expects(:error_and_exit)
|
||||
vm.move_hd
|
||||
end
|
||||
|
||||
should "create assign a new disk image, and delete the old one" do
|
||||
vm = move_hd_expectations
|
||||
@mock_vm.expects(:powered_off?).returns(true)
|
||||
vm.move_hd
|
||||
end
|
||||
|
||||
def move_hd_expectations
|
||||
image, hd = mock('image'), mock('hd')
|
||||
|
||||
Hobo.config[:vm].expects(:hd_location).at_least_once.returns('/locations/')
|
||||
image.expects(:clone).with(Hobo.config[:vm][:hd_location] + 'foo', Hobo::VM::HD_EXT_DEFAULT, true).returns(image)
|
||||
image.expects(:filename).twice.returns('foo')
|
||||
|
||||
hd.expects(:image).twice.returns(image)
|
||||
hd.expects(:image=).with(image)
|
||||
|
||||
image.expects(:destroy)
|
||||
|
||||
@mock_vm.expects(:save)
|
||||
|
||||
vm = Hobo::VM.new(@mock_vm)
|
||||
vm.expects(:hd).times(3).returns(hd)
|
||||
vm
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue