move_hd during hobo up
This commit is contained in:
parent
7fd4ee0160
commit
3a3fbb44c7
|
@ -8,7 +8,7 @@ require 'logger'
|
||||||
require 'virtualbox'
|
require 'virtualbox'
|
||||||
require 'net/ssh'
|
require 'net/ssh'
|
||||||
require 'ping'
|
require 'ping'
|
||||||
require 'hobo/error'
|
require 'hobo/util'
|
||||||
require 'hobo/config'
|
require 'hobo/config'
|
||||||
require 'hobo/env'
|
require 'hobo/env'
|
||||||
require 'hobo/ssh'
|
require 'hobo/ssh'
|
||||||
|
|
|
@ -7,7 +7,7 @@ module Hobo
|
||||||
@config = nil
|
@config = nil
|
||||||
@config_runners = []
|
@config_runners = []
|
||||||
|
|
||||||
class <<self
|
class << self
|
||||||
def config
|
def config
|
||||||
@config ||= Config::Top.new
|
@config ||= Config::Top.new
|
||||||
end
|
end
|
||||||
|
@ -48,6 +48,7 @@ module Hobo
|
||||||
attr_accessor :base_mac
|
attr_accessor :base_mac
|
||||||
attr_accessor :project_directory
|
attr_accessor :project_directory
|
||||||
attr_reader :forwarded_ports
|
attr_reader :forwarded_ports
|
||||||
|
attr_accessor :hd_location
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@forwarded_ports = {}
|
@forwarded_ports = {}
|
||||||
|
@ -60,6 +61,11 @@ module Hobo
|
||||||
:protocol => protocol
|
:protocol => protocol
|
||||||
}
|
}
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
class Top < Base
|
class Top < Base
|
||||||
|
|
|
@ -8,7 +8,7 @@ module Hobo
|
||||||
@@persisted_vm = nil
|
@@persisted_vm = nil
|
||||||
@@root_path = nil
|
@@root_path = nil
|
||||||
|
|
||||||
extend Hobo::Error
|
extend Hobo::Util
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def persisted_vm; @@persisted_vm; end
|
def persisted_vm; @@persisted_vm; end
|
||||||
|
|
|
@ -1,14 +1,19 @@
|
||||||
module Hobo
|
module Hobo
|
||||||
module Error
|
module Util
|
||||||
def error_and_exit(error)
|
def error_and_exit(error)
|
||||||
puts <<-error
|
puts <<-error
|
||||||
=====================================================================
|
=====================================================================
|
||||||
Hobo experienced an error!
|
Hobo experienced an error!
|
||||||
|
|
||||||
#{error.chomp}
|
#{error.chomp}
|
||||||
=====================================================================
|
=====================================================================
|
||||||
error
|
error
|
||||||
exit
|
exit
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def logger
|
||||||
|
HOBO_LOGGER
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
module Hobo
|
module Hobo
|
||||||
class VM
|
class VM
|
||||||
|
HD_EXT_DEFAULT = 'VMDK'
|
||||||
attr_reader :vm
|
attr_reader :vm
|
||||||
|
|
||||||
extend Hobo::Error
|
extend Hobo::Util
|
||||||
|
include Hobo::Util
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
# Bring up the virtual machine. Imports the base image and
|
# Bring up the virtual machine. Imports the base image and
|
||||||
|
@ -28,9 +30,10 @@ module Hobo
|
||||||
def suspend
|
def suspend
|
||||||
Env.require_persisted_vm
|
Env.require_persisted_vm
|
||||||
error_and_exit(<<-error) if Env.persisted_vm.saved?
|
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.
|
suspended state.
|
||||||
error
|
error
|
||||||
|
logger.info "Saving VM state..."
|
||||||
Env.persisted_vm.save_state(true)
|
Env.persisted_vm.save_state(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -59,6 +62,7 @@ error
|
||||||
|
|
||||||
def create
|
def create
|
||||||
import
|
import
|
||||||
|
move_hd if Hobo.config[:vm][:hd_location]
|
||||||
persist
|
persist
|
||||||
setup_mac_address
|
setup_mac_address
|
||||||
forward_ports
|
forward_ports
|
||||||
|
@ -69,26 +73,46 @@ error
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
if @vm.running?
|
if @vm.running?
|
||||||
HOBO_LOGGER.info "VM is running. Forcing immediate shutdown..."
|
logger.info "VM is running. Forcing immediate shutdown..."
|
||||||
@vm.stop(true)
|
@vm.stop(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
HOBO_LOGGER.info "Destroying VM and associated drives..."
|
logger.info "Destroying VM and associated drives..."
|
||||||
@vm.destroy(:destroy_image => true)
|
@vm.destroy(:destroy_image => true)
|
||||||
end
|
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
|
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]))
|
@vm = VirtualBox::VM.import(File.expand_path(Hobo.config[:vm][:base]))
|
||||||
end
|
end
|
||||||
|
|
||||||
def persist
|
def persist
|
||||||
HOBO_LOGGER.info "Persisting the VM UUID (#{@vm.uuid})..."
|
logger.info "Persisting the VM UUID (#{@vm.uuid})..."
|
||||||
Env.persist_vm(@vm)
|
Env.persist_vm(@vm)
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup_mac_address
|
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.nics.first.macaddress = Hobo.config[:vm][:base_mac]
|
||||||
@vm.save(true)
|
@vm.save(true)
|
||||||
end
|
end
|
||||||
|
@ -109,7 +133,7 @@ error
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup_shared_folder
|
def setup_shared_folder
|
||||||
HOBO_LOGGER.info "Creating shared folders..."
|
logger.info "Creating shared folders..."
|
||||||
folder = VirtualBox::SharedFolder.new
|
folder = VirtualBox::SharedFolder.new
|
||||||
folder.name = "hobo-root-path"
|
folder.name = "hobo-root-path"
|
||||||
folder.hostpath = Env.root_path
|
folder.hostpath = Env.root_path
|
||||||
|
@ -126,28 +150,31 @@ error
|
||||||
end
|
end
|
||||||
|
|
||||||
def start
|
def start
|
||||||
HOBO_LOGGER.info "Booting VM..."
|
logger.info "Booting VM..."
|
||||||
@vm.start(:headless, true)
|
@vm.start(:headless, true)
|
||||||
|
|
||||||
# Now we have to wait for the boot to be successful
|
# 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|
|
Hobo.config[:ssh][:max_tries].to_i.times do |i|
|
||||||
sleep 5 unless ENV['HOBO_ENV'] == 'test'
|
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?
|
if Hobo::SSH.up?
|
||||||
HOBO_LOGGER.info "VM booted and ready for use!"
|
logger.info "VM booted and ready for use!"
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
HOBO_LOGGER.info "Failed to connect to VM! Failed to boot?"
|
logger.info "Failed to connect to VM! Failed to boot?"
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def saved?; @vm.saved? end
|
def saved?; @vm.saved? end
|
||||||
|
|
||||||
def save_state(errs); @vm.save_state(errs) 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
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,10 +11,9 @@ if { $port != "" } {
|
||||||
set port_option ""
|
set port_option ""
|
||||||
}
|
}
|
||||||
|
|
||||||
spawn ssh $port_option $uname@$host
|
spawn ssh $port_option -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $uname@$host
|
||||||
|
|
||||||
expect "*password: " {
|
expect "*password: " {
|
||||||
sleep 1
|
|
||||||
send "$password\r"
|
send "$password\r"
|
||||||
} timeout {
|
} timeout {
|
||||||
send_user "Error connecting"
|
send_user "Error connecting"
|
||||||
|
|
|
@ -235,5 +235,41 @@ class VMTest < Test::Unit::TestCase
|
||||||
Hobo::Env.persisted_vm.expects(:start).once.returns(true)
|
Hobo::Env.persisted_vm.expects(:start).once.returns(true)
|
||||||
end
|
end
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue