mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-22 18:50:08 +03:00
feature #863: added a configurable action system and changed some actions to use it
This commit is contained in:
parent
09fe832399
commit
ab10f16d50
@ -37,8 +37,148 @@ require 'ssh_stream'
|
||||
|
||||
require 'pp'
|
||||
|
||||
class VmmAction
|
||||
attr_reader :data
|
||||
|
||||
def initialize(driver, id, action, xml_data)
|
||||
@vmm=driver
|
||||
@id=id
|
||||
@main_action=action
|
||||
@xml_data=@vmm.decode(xml_data)
|
||||
|
||||
@data=Hash.new
|
||||
|
||||
get_data(:host)
|
||||
get_data(:net_drv)
|
||||
get_data(:deploy_id)
|
||||
get_data(:checkpoint_file)
|
||||
|
||||
get_data(:local_dfile, :LOCAL_DEPLOYMENT_FILE)
|
||||
get_data(:remote_dfile, :REMOTE_DEPLOYMENT_FILE)
|
||||
|
||||
# For migration
|
||||
get_data(:dest_host, :MIGR_HOST)
|
||||
get_data(:dest_driver, :MIGR_NET_DRV)
|
||||
|
||||
# Initialize streams and vnm
|
||||
@ssh_src = @vmm.get_ssh_stream(@data[:host], @id)
|
||||
@vnm_src = VirtualNetworkDriver.new(@data[:net_drv],
|
||||
:local_actions => @vmm.options[:local_actions],
|
||||
:message => @xml_data,
|
||||
:ssh_stream => @ssh_src)
|
||||
|
||||
if @data[:dest_host] and !@data[:dest_host].empty?
|
||||
@ssh_dst = @vmm.get_ssh_stream(@data[:dest_host], @id)
|
||||
@vnm_dst = VirtualNetworkDriver.new(@data[:dest_driver],
|
||||
:local_actions => @vmm.options[:local_actions],
|
||||
:message => @xml_data,
|
||||
:ssh_stream => @ssh_dst)
|
||||
end
|
||||
end
|
||||
|
||||
def get_data(name, xml_path=nil)
|
||||
if xml_path
|
||||
path=xml_path.to_s
|
||||
else
|
||||
path=name.to_s.upcase
|
||||
end
|
||||
|
||||
@data[name]=@xml_data.elements[path].text
|
||||
end
|
||||
|
||||
=begin
|
||||
{
|
||||
:driver => :vmm,
|
||||
:action => :deploy,
|
||||
:parameters => [:host, :deploy_id],
|
||||
:destination => false
|
||||
:save_info => :deploy_id,
|
||||
:fail_actions => [],
|
||||
:pre_log => "",
|
||||
:post_log => "",
|
||||
:stdin => nil
|
||||
}
|
||||
=end
|
||||
|
||||
def execute_steps(steps)
|
||||
result=false
|
||||
info='Action #{step[:action]} not found'
|
||||
|
||||
steps.each do |step|
|
||||
|
||||
driver=step[:driver] || :vmm
|
||||
|
||||
@vmm.log(@id, @data[:pre_log]) if @data[:pre_log]
|
||||
|
||||
case driver
|
||||
when :vmm
|
||||
if step[:destination]
|
||||
host = @data[:dest_host]
|
||||
ssh = @ssh_dst
|
||||
else
|
||||
host = @data[:host]
|
||||
ssh = @ssh_src
|
||||
end
|
||||
|
||||
result, info=@vmm.do_action(get_parameters(step), @id, host,
|
||||
step[:action],
|
||||
:ssh_stream => ssh,
|
||||
:respond => false,
|
||||
:stdin => step[:stdin])
|
||||
|
||||
when :vnm
|
||||
if step[:destination]
|
||||
vnm=@vnm_dst
|
||||
else
|
||||
vnm=@vnm_src
|
||||
end
|
||||
|
||||
result, info=vnm.do_action(@id, step[:action])
|
||||
else
|
||||
end
|
||||
|
||||
# Save the info variable if asked for
|
||||
if @data[:save_info]
|
||||
@data[@data[:save_info]]=info
|
||||
end
|
||||
|
||||
if @vmm.failed?(result)
|
||||
if @data[:fail_actions]
|
||||
execute_steps(@data[:fail_actions])
|
||||
end
|
||||
|
||||
break
|
||||
end
|
||||
|
||||
@vmm.log(@id, @data[:post_log]) if @data[:post_log]
|
||||
end
|
||||
|
||||
return result, info
|
||||
end
|
||||
|
||||
def run(steps)
|
||||
result, info=execute_steps(steps)
|
||||
|
||||
@vmm.send_message(VirtualMachineDriver::ACTION[@main_action],
|
||||
result, @id, info)
|
||||
end
|
||||
|
||||
def get_parameters(step)
|
||||
parameters=step[:parameters] || []
|
||||
parameters.map do |param|
|
||||
if Symbol===param
|
||||
@data[param].to_s
|
||||
else
|
||||
param
|
||||
end
|
||||
end.join(' ')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# The main class for the Sh driver
|
||||
class ExecDriver < VirtualMachineDriver
|
||||
attr_reader :options
|
||||
|
||||
# SshDriver constructor
|
||||
def initialize(hypervisor, options={})
|
||||
@ -51,19 +191,21 @@ class ExecDriver < VirtualMachineDriver
|
||||
@hypervisor = hypervisor
|
||||
end
|
||||
|
||||
def get_ssh_stream(host, id)
|
||||
SshStreamCommand.new(host,
|
||||
@remote_scripts_base_path,
|
||||
log_method(id))
|
||||
end
|
||||
|
||||
# DEPLOY action, sends the deployment file to remote host
|
||||
def deploy(id, drv_message)
|
||||
# ----------------------------------------------------------------------
|
||||
# Initialization of deployment data
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
data = decode(drv_message)
|
||||
action=VmmAction.new(self, id, :deploy, drv_message)
|
||||
|
||||
local_dfile = data.elements['LOCAL_DEPLOYMENT_FILE'].text
|
||||
remote_dfile = data.elements['REMOTE_DEPLOYMENT_FILE'].text
|
||||
|
||||
host = data.elements['HOST'].text
|
||||
net_drv = data.elements['NET_DRV'].text
|
||||
local_dfile=action.data[:local_dfile]
|
||||
|
||||
if !local_dfile || File.zero?(local_dfile)
|
||||
send_message(ACTION[:deploy],RESULT[:failure],id,
|
||||
@ -74,263 +216,146 @@ class ExecDriver < VirtualMachineDriver
|
||||
domain = File.read(local_dfile)
|
||||
|
||||
if action_is_local?(:deploy)
|
||||
dfile = local_dfile
|
||||
dfile = action.data[:local_dfile]
|
||||
else
|
||||
dfile = remote_dfile
|
||||
dfile = action.data[:remote_dfile]
|
||||
end
|
||||
|
||||
ssh = SshStreamCommand.new(host,
|
||||
@remote_scripts_base_path,
|
||||
log_method(id))
|
||||
steps=[
|
||||
{
|
||||
:driver => :vnm,
|
||||
:action => :pre,
|
||||
:post_log => "Successfully executed network driver " <<
|
||||
"#{action.data[:net_drv]} (pre-boot)"
|
||||
},
|
||||
{
|
||||
:driver => :vmm,
|
||||
:action => :deploy,
|
||||
:parameters => [dfile, :host],
|
||||
:stdin => domain,
|
||||
:save_info => :deploy_id
|
||||
},
|
||||
{
|
||||
:driver => :vnm,
|
||||
:action => :post,
|
||||
:fail_actions => [
|
||||
{
|
||||
:driver => :vmm,
|
||||
:action => :cancel,
|
||||
:parameters => [:deploy_id, :host]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
vnm = VirtualNetworkDriver.new(net_drv,
|
||||
:local_actions => @options[:local_actions],
|
||||
:message => data,
|
||||
:ssh_stream => ssh)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Execute pre-boot action of the network driver
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
result, info = vnm.do_action(id, :pre)
|
||||
|
||||
if failed?(result)
|
||||
send_message(ACTION[:deploy], result, id,info)
|
||||
return
|
||||
end
|
||||
|
||||
log(id, "Successfully executed network driver #{net_drv} (pre-boot)")
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Boot the VM
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
result, info = do_action("#{dfile} #{host}", id, host, :deploy,
|
||||
:stdin => domain,
|
||||
:ssh_stream => ssh,
|
||||
:respond => false)
|
||||
if failed?(result)
|
||||
send_message(ACTION[:deploy], result, id, info)
|
||||
return
|
||||
end
|
||||
|
||||
deploy_id = info
|
||||
|
||||
log(id, "Successfully booted VM with id: #{deploy_id}")
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Execute post-boot action of the network driver
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
result, info = vnm.do_action(id, :post)
|
||||
|
||||
if failed?(result)
|
||||
log(id, "Failed to executed network driver #{net_drv} (post-boot)")
|
||||
log(id, "Canceling VM with id: #{deploy_id}")
|
||||
|
||||
do_action("#{deploy_id} #{host}", id, host, :cancel,
|
||||
:ssh_stream => ssh,
|
||||
:respond => false)
|
||||
|
||||
send_message(ACTION[:deploy], result, id, info)
|
||||
return
|
||||
end
|
||||
|
||||
log(id, "Successfully executed network driver #{net_drv} (post-boot)")
|
||||
|
||||
send_message(ACTION[:deploy], RESULT[:success], id, deploy_id)
|
||||
action.run(steps)
|
||||
end
|
||||
|
||||
# Basic Domain Management Operations
|
||||
|
||||
def shutdown(id, drv_message)
|
||||
data = decode(drv_message)
|
||||
host = data.elements['HOST'].text
|
||||
net_drv = data.elements['NET_DRV'].text
|
||||
deploy_id = data.elements['DEPLOY_ID'].text
|
||||
action=VmmAction.new(self, id, :shutdown, drv_message)
|
||||
|
||||
ssh = SshStreamCommand.new(host,
|
||||
@remote_scripts_base_path,
|
||||
log_method(id))
|
||||
steps=[
|
||||
{
|
||||
:driver => :vmm,
|
||||
:action => :shutdown,
|
||||
:parameters => [:deploy_id, :host],
|
||||
:post_log => "Successfully shut down VM with id: " <<
|
||||
action.data[:deploy_id]
|
||||
},
|
||||
{
|
||||
:driver => :vnm,
|
||||
:action => :clean,
|
||||
:post_log => "Successfully executed network driver " <<
|
||||
"#{action.data[:net_drv]} (clean-shutdown)"
|
||||
}
|
||||
}
|
||||
|
||||
vnm = VirtualNetworkDriver.new(net_drv,
|
||||
:local_actions => @options[:local_actions],
|
||||
:message => data,
|
||||
:ssh_stream => ssh)
|
||||
|
||||
result, info = do_action("#{deploy_id} #{host}", id, host, :shutdown,
|
||||
:ssh_stream => ssh,
|
||||
:respond => false)
|
||||
|
||||
if failed?(result)
|
||||
send_message(ACTION[:shutdown], result, id,info)
|
||||
return
|
||||
end
|
||||
|
||||
log(id, "Successfully shut down VM with id: #{deploy_id}")
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Execute clean action of the network driver
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
result, info = vnm.do_action(id, :clean)
|
||||
|
||||
if failed?(result)
|
||||
send_message(ACTION[:shutdown], result, id,info)
|
||||
return
|
||||
end
|
||||
|
||||
log(id, "Successfully executed network driver #{net_drv}" <<
|
||||
" (clean-shutdown)")
|
||||
action.run(steps)
|
||||
end
|
||||
|
||||
def cancel(id, drv_message)
|
||||
data = decode(drv_message)
|
||||
host = data.elements['HOST'].text
|
||||
net_drv = data.elements['NET_DRV'].text
|
||||
deploy_id = data.elements['DEPLOY_ID'].text
|
||||
action=VmmAction.new(self, id, :cancel, drv_message)
|
||||
|
||||
ssh = SshStreamCommand.new(host,
|
||||
@remote_scripts_base_path,
|
||||
log_method(id))
|
||||
steps=[
|
||||
{
|
||||
:driver => :vmm,
|
||||
:action => :cancel,
|
||||
:parameters => [:deploy_id, :host],
|
||||
:post_log => "Successfully canceled VM with id: " <<
|
||||
action.data[:deploy_id]
|
||||
},
|
||||
{
|
||||
:driver => :vnm,
|
||||
:action => :clean,
|
||||
:post_log => "Successfully executed network driver " <<
|
||||
"#{action.data[:net_drv]} (clean-cancel)"
|
||||
}
|
||||
]
|
||||
|
||||
vnm = VirtualNetworkDriver.new(net_drv,
|
||||
:local_actions => @options[:local_actions],
|
||||
:message => data,
|
||||
:ssh_stream => ssh)
|
||||
|
||||
result, info = do_action("#{deploy_id} #{host}", id, host, :cancel,
|
||||
:ssh_stream => ssh,
|
||||
:respond => false)
|
||||
|
||||
if failed?(result)
|
||||
send_message(ACTION[:cancel], result, id,info)
|
||||
return
|
||||
end
|
||||
|
||||
log(id, "Successfully canceled VM with id: #{deploy_id}")
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Execute clean action of the network driver
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
result, info = vnm.do_action(id, :clean)
|
||||
|
||||
if failed?(result)
|
||||
send_message(ACTION[:cancel], result, id,info)
|
||||
return
|
||||
end
|
||||
|
||||
log(id, "Successfully executed network driver #{net_drv}" <<
|
||||
" (clean-cancel)")
|
||||
|
||||
send_message(ACTION[:shutdown], RESULT[:success], id, deploy_id)
|
||||
action.run(steps)
|
||||
end
|
||||
|
||||
def save(id, drv_message)
|
||||
data = decode(drv_message)
|
||||
host = data.elements['HOST'].text
|
||||
net_drv = data.elements['NET_DRV'].text
|
||||
deploy_id = data.elements['DEPLOY_ID'].text
|
||||
file = data.elements['CHECKPOINT_FILE'].text
|
||||
action=VmmAction.new(self, id, :save, drv_message)
|
||||
|
||||
ssh = SshStreamCommand.new(host,
|
||||
@remote_scripts_base_path,
|
||||
log_method(id))
|
||||
steps=[
|
||||
{
|
||||
:driver => :vmm,
|
||||
:action => :save,
|
||||
:parameters => [:deploy_id, :checkpoint_file, :host],
|
||||
:post_log => "Successfully saved VM with id: " <<
|
||||
action.data[:deploy_id]
|
||||
},
|
||||
{
|
||||
:driver => :vnm,
|
||||
:action => :clean,
|
||||
:post_log => "Successfully executed network driver " <<
|
||||
"#{action.data[:net_drv]} (clean-save)"
|
||||
}
|
||||
]
|
||||
|
||||
vnm = VirtualNetworkDriver.new(net_drv,
|
||||
:local_actions => @options[:local_actions],
|
||||
:message => data,
|
||||
:ssh_stream => ssh)
|
||||
|
||||
result, info = do_action("#{deploy_id} #{file} #{host}", id, host,
|
||||
:save,
|
||||
:ssh_stream => ssh,
|
||||
:respond => false)
|
||||
|
||||
if failed?(result)
|
||||
send_message(ACTION[:save], result, id,info)
|
||||
return
|
||||
end
|
||||
|
||||
log(id, "Successfully saved VM with id: #{deploy_id}")
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Execute clean action of the network driver
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
result, info = vnm.do_action(id, :clean)
|
||||
|
||||
if failed?(result)
|
||||
send_message(ACTION[:save], result, id,info)
|
||||
return
|
||||
end
|
||||
|
||||
log(id, "Successfully executed network driver #{net_drv}" <<
|
||||
" (clean-save)")
|
||||
|
||||
send_message(ACTION[:save], RESULT[:success], id, domain_id)
|
||||
action.run(steps)
|
||||
end
|
||||
|
||||
def restore(id, drv_message)
|
||||
data = decode(drv_message)
|
||||
host = data.elements['HOST'].text
|
||||
file = data.elements['CHECKPOINT_FILE'].text
|
||||
action=VmmAction.new(self, id, :restore, drv_message)
|
||||
|
||||
ssh = SshStreamCommand.new(host,
|
||||
@remote_scripts_base_path,
|
||||
log_method(id))
|
||||
steps=[
|
||||
{
|
||||
:driver => :vnm,
|
||||
:action => :pre,
|
||||
:post_log => "Successfully executed network driver " <<
|
||||
"#{action.data[:net_drv]} (pre-restore)"
|
||||
},
|
||||
{
|
||||
:driver => :vmm,
|
||||
:action => :restore,
|
||||
:parameters => [:checkpoint_file, :host],
|
||||
:save_info => :deploy_id,
|
||||
:post_log => "Successfully restored VM with id: " <<
|
||||
action.data[:deploy_id]
|
||||
},
|
||||
{
|
||||
:driver => :vnm,
|
||||
:action => :post,
|
||||
:fail_actions => [
|
||||
{
|
||||
:pre_log => "Failed to execute network driver" <<
|
||||
"#{action.data[:net_drv]} (post-restore). " <<
|
||||
"Cancelling VM with id: #{action.data[:deploy_id]}"
|
||||
:driver => :vmm,
|
||||
:action => :cancel,
|
||||
:parameters => [:deploy_id, :host]
|
||||
}
|
||||
],
|
||||
:post_log => "Successfully executed network driver " <<
|
||||
"#{action.data[:net_drv]} (post-restore)"
|
||||
}
|
||||
]
|
||||
|
||||
vnm = VirtualNetworkDriver.new(net_drv,
|
||||
:local_actions => @options[:local_actions],
|
||||
:message => data,
|
||||
:ssh_stream => ssh)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Execute pre-boot action of the network driver
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
result, info = vnm.do_action(id, :pre)
|
||||
|
||||
if failed?(result)
|
||||
send_message(ACTION[:restore], result, id,info)
|
||||
return
|
||||
end
|
||||
|
||||
log(id, "Successfully executed network driver #{net_drv} (pre-restore)")
|
||||
|
||||
result, info = do_action("#{file} #{host}", id, host, :restore,
|
||||
:save,
|
||||
:ssh_stream => ssh,
|
||||
:respond => false)
|
||||
if failed?(result)
|
||||
send_message(ACTION[:restore], result, id, info)
|
||||
return
|
||||
end
|
||||
|
||||
log(id, "Successfully restored VM with id: #{info}")
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Execute post-restore action of the network driver
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
result, info = vnm.do_action(id, :post)
|
||||
|
||||
if failed?(result)
|
||||
log(id, "Failed to executed network driver #{net_drv} (post-restore)")
|
||||
log(id, "Canceling VM with id: #{domain_id}")
|
||||
|
||||
do_action("#{domain_id} #{host}", id, host, :cancel,
|
||||
:ssh_stream => ssh,
|
||||
:respond => false)
|
||||
|
||||
send_message(ACTION[:restore], result, id, info)
|
||||
return
|
||||
end
|
||||
|
||||
log(id, "Successfully executed network driver #{net_drv} (post-restore)")
|
||||
|
||||
send_message(ACTION[:restore], RESULT[:success], id, domain_id)
|
||||
action.run(steps)
|
||||
end
|
||||
|
||||
def migrate(id, drv_message)
|
||||
@ -455,3 +480,5 @@ exec_driver = ExecDriver.new(hypervisor,
|
||||
:local_actions => local_actions)
|
||||
|
||||
exec_driver.start_driver
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user