Merging in VirtualBox control functionality from Hauke / Fidius Project

git-svn-id: file:///home/svn/framework3/trunk@11753 4d416f70-5f16-0410-b530-b9f4589650da
unstable
Jonathan Cran 2011-02-16 02:15:24 +00:00
parent a27a545889
commit 5172768cb9
9 changed files with 221 additions and 128 deletions

View File

@ -3,6 +3,7 @@ require 'vm_driver'
##
## $Id$
##
module Lab
module Drivers
class AmazonDriver < VmDriver
@ -21,16 +22,7 @@ module Drivers
@access_key = key
@secret_access_key = secret_key
@location = filter_input(location)
@type = "ec2"
end
def filter_input(string)
if !(string =~ /^[[:alnum:]\/\\\-\.\(\)\ _]*$/)
raise ArgumentError,"Invalid character in: #{string}"
end
return string.gsub(/^[^[:alnum:]\/\\\-\.\(\)\ _]*$/, '')
@type = "amazon"
end
def register
@ -86,19 +78,6 @@ module Drivers
end
def running?
## Get running Vms
running = `dynagen ?` #TODO
running_array = running.split("\n")
## Skip the first 4 lines of output
4.times { running_array.shift }
running_array.each do |vmx|
if vmx.to_s == @location.to_s
return true
end
end
return false
end
end

View File

@ -88,7 +88,6 @@ module Drivers
end
def cleanup
`killall dynagen`
`killall dynamips`
@running = false

View File

@ -14,20 +14,16 @@ class RemoteWorkstationDriver < VmDriver
def initialize(location, user=nil, host=nil, credentials=nil)
## Can we check file existence?
#if !File.exist?(location)
# raise ArgumentError,"Couldn't find: " + location
#end
## TODO - Should proabably check file existence?
unless user then raise ArgumentError, "Must provide a username" end
unless host then raise ArgumentError, "Must provide a hostname" end
@location = filter_input(location)
@host = filter_input(host)
@user = filter_input(user)
@host = filter_input(host)
@credentials = filter_input_credentials(credentials)
@type = "RemoteWorkstation"
@type = "remote_workstation"
end
def start
@ -51,14 +47,17 @@ class RemoteWorkstationDriver < VmDriver
end
def create_snapshot(snapshot)
snapshot = filter_input(snapshot)
system_command("ssh #{@user}@#{@host} vmrun -T ws snapshot \\\'#{@location}\\\' #{snapshot} nogui")
end
def revert_snapshot(snapshot)
snapshot = filter_input(snapshot)
system_command("ssh #{@user}@#{@host} vmrun -T ws revertToSnapshot \\\'#{@location}\\\' #{snapshot} nogui")
end
def delete_snapshot(snapshot)
snapshot = filter_input(snapshot)
system_command("ssh #{@user}@#{@host} vmrun -T ws deleteSnapshot \\\'#{@location}\\\' #{snapshot} nogui" )
end
@ -69,7 +68,7 @@ class RemoteWorkstationDriver < VmDriver
## this will return the first user if named_user doesn't exist
## -- that may not be entirely obvious...
cred = get_best_credentials(named_user)
cred = get_best_creds(named_user)
user = cred['user']
pass = cred['pass']
@ -87,7 +86,7 @@ class RemoteWorkstationDriver < VmDriver
## this will return the first user if named_user doesn't exist
## -- that may not be entirely obvious...
cred = get_best_credentials(named_user)
cred = get_best_creds(named_user)
user = cred['user']
pass = cred['pass']
@ -104,7 +103,7 @@ class RemoteWorkstationDriver < VmDriver
## this will return the first user if named_user doesn't exist
## -- that may not be entirely obvious...
cred = get_best_credentials(named_user)
cred = get_best_creds(named_user)
user = cred['user']
pass = cred['pass']
@ -121,7 +120,7 @@ class RemoteWorkstationDriver < VmDriver
## this will return the first user if named_user doesn't exist
## -- that may not be entirely obvious...
cred = get_best_credentials(named_user)
cred = get_best_creds(named_user)
user = cred['user']
pass = cred['pass']
@ -138,7 +137,7 @@ class RemoteWorkstationDriver < VmDriver
## this will return the first user if named_user doesn't exist
## -- that may not be entirely obvious...
cred = get_best_credentials(named_user)
cred = get_best_creds(named_user)
user = cred['user']
pass = cred['pass']

View File

@ -0,0 +1,22 @@
module Lab
module Controllers
module VirtualBoxController
def self.running_list
vm_names_and_uuids = `VBoxManage list runningvms`.split("\n")
4.times { vm_names_and_uuids.shift }
vm_names = []
vm_names_and_uuids.each do |entry|
vm_names << entry.split('"')[1]
end
return vm_names
end
def self.dir_list(basepath=nil)
vm_list = Find.find(basepath).select { |f| f =~ /\.xml$/ }
end
end
end
end

View File

@ -1,4 +1,5 @@
require 'vm_driver'
require 'nokogiri'
##
## $Id$
@ -10,105 +11,157 @@ module Drivers
attr_accessor :type
attr_accessor :location
def initialize(location)
if !File.exist?(location)
raise ArgumentError,"Couldn't find: " + location
end
def initialize(vmid, location=nil)
@vmid = filter_input(vmid)
@location = filter_input(location)
@type = "vbox"
@name = ""
register
@type = "virtualbox"
## Check to see if we already know this vm, if not, go on location
vmid_list = get_vm_names
unless vmid_list.include? @vmid
raise "Error, no such vm: #{@vmid}" unless @location
if !File.exist?(@location)
raise ArgumentError,"Error, no vm at: #{@location}"
end
puts "Registering #{@location}"
@vmid = register_and_return_vmid
end
vmInfo = `VBoxManage showvminfo \"#{@vmid}\" --machinereadable`
@location = vmInfo.scan(/CfgFile=\"(.*?)\"/).flatten.to_s
end
def register
name_string = `VBoxManage registervm #{@location}`
##TODO - parse out name / uuid
def register_and_return_vmid
xml = Nokogiri::XML(File.new(@location))
vmid = xml.root.xpath("//Machine[@name]")
## only register if we don't already know the vmid
if !get_vm_names.include? vmid
system_command("VBoxManage registervm \"#{@location}\"")
end
return vmid
end
def unregister
system_command("VBoxManage unregistervm #{@name}")
system_command("VBoxManage unregistervm \"#{@vmid}\"")
end
def start
system_command("VBoxManage startvm #{@name}")
system_command("VBoxManage startvm \"#{@vmid}\"")
end
def stop
system_command("VBoxManage controlvm#{@name} poweroff")
system_command("VBoxManage controlvm \"#{@vmid}\" poweroff")
end
def suspend
system_command("VBoxManage controlvm #{@name} pause")
system_command("VBoxManage controlvm \"#{@vmid}\" savestate")
end
def pause
system_command("VBoxManage controlvm #{@name} pause")
system_command("VBoxManage controlvm \"#{@vmid}\" pause")
end
def reset
system_command("VBoxManage controlvm #{@name} reset")
system_command("VBoxManage controlvm \"#{@vmid}\" reset")
end
def create_snapshot(name)
system_command("VBoxManage snapshot #{@name} take " + name)
def create_snapshot(snapshot)
snapshot = filter_input(snapshot)
system_command("VBoxManage snapshot \"#{@vmid}\" take " + snapshot)
end
def revert_snapshot(name)
system_command("VBoxManage snapshot #{@name} restore " + name)
def revert_snapshot(snapshot)
snapshot = filter_input(snapshot)
system_command("VBoxManage snapshot \"#{@vmid}\" restore " + snapshot)
end
def delete_snapshot(name)
system_command("VBoxManage snapshot #{@name} delete " + name )
def delete_snapshot(snapshot)
snapshot = filter_input(snapshot)
system_command("VBoxManage snapshot \"#{@vmid}\" delete " + snapshot)
end
def run_command(command, arguments, user, pass)
command = "VBoxManage execute #{@name} #{command} --username #{username}
--password #{password} --arguments \"#{arguments}\""
command = "VBoxManage guestcontrol exec \"#{@vmid}\" \"#{command}\" --username \"#{user}\"
--password \"#{pass}\" --arguments \"#{arguments}\""
system_command(command)
end
def copy_from(user, pass, from, to)
command = "VBoxManage " ##TODO
system_command(command)
raise "Not supported by Virtual Box"
end
def copy_to(user, pass, from, to)
command = "VBoxManage " ##TODO
command = "VBoxManage guestcontrol copyto \"#{@vmid}\" \"#{from}\" \"#{to}\"
--username \"#{user}\" --password \"#{pass}\""
system_command(command)
end
def check_file_exists(user, pass, file)
command = "VBoxManage " ##TODO
system_command(command)
raise "Not supported by Virtual Box"
end
def create_directory(user, pass, directory)
command = "VBoxManage " ##TODO
command = "VBoxManage guestcontrol createdir \"#{@vmid}\" \"#{directory}\"
--username \"#{user}\" --password \"#{pass}\""
system_command(command)
end
def cleanup
self.unregister
end
def running?
## Get running Vms
running = `VBoxManage list runningvms`
running_array = running.split("\n")
get_running_vm_names.include? @vmid
end
private
def get_vm_names
## Get Known VMs
vm_names_and_uuids = `VBoxManage list vms`.split("\n")
4.times { vm_names_and_uuids.shift }
## Skip the first 4 lines of output
4.times { running_array.shift }
vm_names = []
vm_names_and_uuids.each do |entry|
vm_names << entry.split('"')[1]
end
return vm_names
end
running_array.each do |vmx|
if vmx.to_s == @location.to_s
return true
end
def get_vm_uuids
## Get Known VMs
vm_names_and_uuids = `VBoxManage list vms`.split("\n")
4.times { vm_names_and_uuids.shift }
vm_uuids = []
vm_names_and_uuids.each do |entry|
vm_names << entry.split('"')[2]
end
return vm_uuids
end
def get_running_vm_names
## Get Known VMs
vm_names_and_uuids = `VBoxManage list runningvms`.split("\n")
4.times { vm_names_and_uuids.shift }
return false
vm_names = []
vm_names_and_uuids.each do |entry|
vm_names << entry.split('"')[1]
end
return vm_names
end
end
end

View File

@ -5,7 +5,7 @@
require 'workstation_driver'
require 'remote_workstation_driver'
#require 'dynagen_driver'
#require 'virtualbox_driver'
require 'virtualbox_driver'
#require 'amazon_driver'
module Lab
@ -14,7 +14,6 @@ class Vm
attr_accessor :vmid
attr_accessor :driver
attr_accessor :location
attr_accessor :credentials
attr_accessor :tools
attr_accessor :type
@ -27,15 +26,18 @@ class Vm
## location (file / uri)
## credentials (of the form [ {'user'=>"user",'pass'=>"pass", 'admin' => false}, ... ])
def initialize(config = {})
## Mandatory
@vmid = config['vmid']
raise Exception, "Invalid VMID" unless @vmid
@driver = nil
driver_type = config['driver']
driver_type.downcase!
## Mandatory
@vmid = config['vmid']
@location = config['location']
## Optional
@location = config['location'] ## only optional in the case of virtualbox (currently)
@type = config['type'] || "unspecified"
@tools = config['tools'] || false ## TODO
@credentials = config['credentials'] || []
@ -43,7 +45,7 @@ class Vm
@ports = nil ## TODO
@vulns = nil ## TODO
## Remote
## Only applicable to remote systems
@user = config['user'] || nil
@host = config['host'] || nil
@ -51,12 +53,12 @@ class Vm
@driver = Lab::Drivers::WorkstationDriver.new(@location, @credentials)
elsif driver_type == "remote_workstation"
@driver = Lab::Drivers::RemoteWorkstationDriver.new(@location, @user, @host, @credentials)
elsif driver_type == "dynagen"
@driver = Lab::Drivers::DynagenDriver.new
#elsif driver_type == "dynagen"
# @driver = Lab::Drivers::DynagenDriver.new
elsif driver_type == "virtualbox"
@driver = Lab::Drivers::VirtualBoxDriver.new
elsif driver_type == "amazon"
@driver = Lab::Drivers::AmazonDriver.new
@driver = Lab::Drivers::VirtualBoxDriver.new(@vmid, @location)
#elsif driver_type == "amazon"
# @driver = Lab::Drivers::AmazonDriver.new
else
raise Exception, "Unknown Driver Type"
end
@ -67,6 +69,10 @@ class Vm
@driver.running?
end
def location
@driver.location
end
def start
@driver.start
end
@ -131,8 +137,8 @@ class Vm
def to_yaml
out = " - vmid: #{@vmid}\n"
out += " driver: #{@driver.type}\n"
out += " location: #{@location}\n"
out = " type: #{@type}\n"
out += " location: #{@driver.location}\n"
out += " type: #{@type}\n"
out += " tools: #{@tools}\n"
out += " credentials:\n"
@credentials.each do |credential|

View File

@ -15,7 +15,7 @@ require 'workstation_controller'
require 'remote_workstation_controller'
#require 'qemu_controller'
#require 'amazon_controller'
#require 'virtualbox_controller'
require 'virtualbox_controller'
#require 'dynagen_controller'
module Lab
@ -27,7 +27,7 @@ module Controllers
include Lab::Controllers::RemoteWorkstationController ## gives access to workstation-specific controller methods
#include Lab::Controllers::QemuController ## gives access to qemu-specific controller methods
#include Lab::Controllers::AmazonController ## gives access to amazon-specific controller methods
#include Lab::Controllers::VirtualBoxController ## gives access to virtualbox-specific controller methods
include Lab::Controllers::VirtualBoxController ## gives access to virtualbox-specific controller methods
#include Lab::Controllers::DynagenController ## gives access to dynagen-specific controller methods
@ -47,7 +47,7 @@ module Controllers
begin
@vms << Vm.new(item)
rescue Exception => e
puts e.to_s
puts "Invalid VM definition"
end
end
@ -110,7 +110,7 @@ module Controllers
@vms.each { |vm| if (vm.vmid.to_s == vmid.to_s) then return true end }
end
def build_from_dir(dir, type, clear=false)
def build_from_dir(type, dir, clear=false)
if clear
@vms = []
@ -120,13 +120,15 @@ module Controllers
vm_list = ::Lab::Controllers::WorkstationController::dir_list(dir)
elsif type.downcase == "remote_workstation"
vm_list = ::Lab::Controllers::RemoteWorkstationController::dir_list(dir)
elsif type.downcase == "virtualbox"
vm_list = ::Lab::Controllers::VirtualBoxController::dir_list(dir)
else
raise TypeError, "Unsupported VM Type"
end
vm_list.each do |item|
index = @vms.count + 1
@vms << Vm.new( {"vmid" => index, "driver" => type, "location" => item} )
vm_list.each_index do |index|
puts "Creating VM object for: " + vm_list[index]
@vms << Vm.new( {'vmid' => index.to_s, 'driver' => type, 'location' => vm_list[index]} )
end
end
@ -137,28 +139,53 @@ module Controllers
end
case type.intern
when :workstation
vm_list = ::Lab::Controllers::WorkstationController::running_list
when :remote_workstation
vm_list = ::Lab::Controllers::RemoteWorkstationController::running_list(user, host)
else
raise TypeError, "Unsupported VM Type"
end
vm_list.each do |item|
when :workstation
vm_list = ::Lab::Controllers::WorkstationController::running_list
vm_list.each do |item|
## Name the VM
index = @vms.count + 1
## Name the VM
index = @vms.count + 1
## Add it to the vm list
@vms << Vm.new( { 'vmid' => index,
'driver' => type,
'location' => item,
'user' => user,
'host' => host } )
end
## Add it to the vm list
@vms << Vm.new( { 'vmid' => index.to_s,
'driver' => type,
'location' => item,
'user' => user,
'host' => host } )
end
when :remote_workstation
vm_list = ::Lab::Controllers::RemoteWorkstationController::running_list(user, host)
vm_list.each do |item|
## Name the VM
index = @vms.count + 1
## Add it to the vm list
@vms << Vm.new( { 'vmid' => "#{index}",
'driver' => type,
'location' => item,
'user' => user,
'host' => host } )
end
when :virtualbox
vm_list = ::Lab::Controllers::VirtualBoxController::running_list
vm_list.each do |item|
## Add it to the vm list
@vms << Vm.new( { 'vmid' => "#{item}",
'driver' => type,
'location' => nil,
'user' => user,
'host' => host } )
end
else
raise TypeError, "Unsupported VM Type"
end
end

View File

@ -86,15 +86,20 @@ class VmDriver
private
def filter_input(string)
if !(string =~ /^[[:alnum:]\/\\\-\.\(\)\ _]*$/)
return unless string
if !(string =~ /^[\w\s\[\]\{\}\/\\\.\-\"\(\)]*$/)
raise Exception, "Invalid character in: #{string}"
end
return string.gsub(/^[^[:alnum:]\/\\\-\.\(\)\ _]*$/, '')
return string
return string.gsub(/^[\w\s\[\]\{\}\/\\\.\-\"\(\)]*$/, "Invalid String")
end
def filter_input_credentials(credentials)
return unless credentials
credentials.each { |credential|
credential['user'] = filter_input(credential['user'])
credential['pass'] = filter_input(credential['pass'])

View File

@ -21,7 +21,7 @@ class WorkstationDriver < VmDriver
@credentials = filter_input_credentials(credentials)
@type = "Workstation"
@type = "workstation"
end
@ -46,15 +46,18 @@ class WorkstationDriver < VmDriver
end
def create_snapshot(snapshot)
system_command("vmrun -T ws snapshot " + "\"#{@location}\" \"#{@snapshot}\"")
snapshot = filter_input(snapshot)
system_command("vmrun -T ws snapshot " + "\"#{@location}\" \"#{snapshot}\"")
end
def revert_snapshot(snapshot)
system_command("vmrun -T ws revertToSnapshot " + "\"#{@location}\" \"#{@snapshot}\"")
snapshot = filter_input(snapshot)
system_command("vmrun -T ws revertToSnapshot " + "\"#{@location}\" \"#{snapshot}\"")
end
def delete_snapshot(snapshot)
system_command("vmrun -T ws deleteSnapshot " + "\"#{@location}\" \"#{@snapshot}\"" )
snapshot = filter_input(snapshot)
system_command("vmrun -T ws deleteSnapshot " + "\"#{@location}\" \"#{snapshot}\"" )
end
def run_command(command, named_user=nil)
@ -63,7 +66,7 @@ class WorkstationDriver < VmDriver
## this will return the first user if named_user doesn't exist
## -- that may not be entirely obvious...
cred = get_best_credentials(named_user)
cred = get_best_creds(named_user)
user = cred['user']
pass = cred['pass']
@ -81,7 +84,7 @@ class WorkstationDriver < VmDriver
## this will return the first user if named_user doesn't exist
## -- that may not be entirely obvious...
cred = get_best_credentials(named_user)
cred = get_best_creds(named_user)
user = cred['user']
pass = cred['pass']
@ -98,7 +101,7 @@ class WorkstationDriver < VmDriver
## this will return the first user if named_user doesn't exist
## -- that may not be entirely obvious...
cred = get_best_credentials(named_user)
cred = get_best_creds(named_user)
user = cred['user']
pass = cred['pass']
@ -115,7 +118,7 @@ class WorkstationDriver < VmDriver
## this will return the first user if named_user doesn't exist
## -- that may not be entirely obvious...
cred = get_best_credentials(named_user)
cred = get_best_creds(named_user)
user = cred['user']
pass = cred['pass']
@ -132,7 +135,7 @@ class WorkstationDriver < VmDriver
## this will return the first user if named_user doesn't exist
## -- that may not be entirely obvious...
cred = get_best_credentials(named_user)
cred = get_best_creds(named_user)
user = cred['user']
pass = cred['pass']