1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-26 10:03:37 +03:00

Added new driver files.

EC2 driver cleanups, minimizing changes.

Added default timeout constant.
This commit is contained in:
Alejandro Huertas 2018-07-17 11:35:57 +02:00 committed by Tino Vázquez
parent e27bd982f6
commit bdf301c0cd
2 changed files with 123 additions and 40 deletions

View File

@ -31,12 +31,15 @@ require 'ec2_driver'
deploy_id = ARGV[0]
host = ARGV[1]
vm_id = ARGV[2]
begin
one = OpenNebula::Client.new()
vm = OpenNebula::VirtualMachine.new_with_id(vm_id, one)
vm.info
ec2_drv = EC2Driver.new(host)
ec2_drv.cancel(deploy_id)
ec2_drv.cancel(deploy_id, vm.lcm_state_str)
rescue Exception => e
OpenNebula.handle_driver_exception("Cancel", e, host, deploy_id)
end

View File

@ -30,6 +30,8 @@ end
EC2_DRIVER_CONF = "#{ETC_LOCATION}/ec2_driver.conf"
EC2_DRIVER_DEFAULT = "#{ETC_LOCATION}/ec2_driver.default"
STATE_WAIT_PM_TIMEOUT_SECONDS = 1500
gem 'aws-sdk', '>= 2.0'
# Load EC2 credentials and environment
@ -229,7 +231,11 @@ class EC2Driver
@host = host
@host_id = host_id
@state_change_timeout = PUBLIC_CLOUD_EC2_CONF['state_wait_timeout_seconds'].to_i
if host['PM_MAD']
@state_change_timeout = PUBLIC_CLOUD_EC2_CONF['state_wait_pm_timeout_seconds'] ? PUBLIC_CLOUD_EC2_CONF['state_wait_pm_timeout_seconds'].to_i : STATE_WAIT_PM_TIMEOUT_SECONDS
else
@state_change_timeout = PUBLIC_CLOUD_EC2_CONF['state_wait_timeout_seconds'].to_i
end
@instance_types = PUBLIC_CLOUD_EC2_CONF['instance_types']
@ -263,10 +269,15 @@ class EC2Driver
conn_opts={}
client = OpenNebula::Client.new
pool = OpenNebula::HostPool.new(client)
pool.info
objects=pool.select {|object| object.name==host }
xmlhost = objects.first
if host.is_a?(String)
pool = OpenNebula::HostPool.new(client)
pool.info
objects=pool.select {|object| object.name==host }
xmlhost = objects.first
else
xmlhost = host
end
system = OpenNebula::System.new(client)
config = system.get_configuration
@ -274,14 +285,23 @@ class EC2Driver
token = config["ONE_KEY"]
if xmlhost["TEMPLATE/PROVISION"]
@tmplBase = 'TEMPLATE/PROVISION'
else
@tmplBase = 'TEMPLATE'
end
conn_opts = {
:access => xmlhost["TEMPLATE/EC2_ACCESS"],
:secret => xmlhost["TEMPLATE/EC2_SECRET"]
:access => xmlhost["#{@tmplBase}/EC2_ACCESS"],
:secret => xmlhost["#{@tmplBase}/EC2_SECRET"]
}
begin
conn_opts = OpenNebula.decrypt(conn_opts, token)
conn_opts[:region] = xmlhost["TEMPLATE/REGION_NAME"]
if !xmlhost["TEMPLATE/PROVISION"]
conn_opts = OpenNebula.decrypt(conn_opts, token)
end
conn_opts[:region] = xmlhost["#{@tmplBase}/REGION_NAME"]
rescue
raise "HOST: #{host} must have ec2 credentials and region in order to work properly"
end
@ -289,6 +309,21 @@ class EC2Driver
return conn_opts
end
# Generate cloud-init configuration based on context variables
def generate_cc(xobj, xpath_context)
cc = "#cloud-config\n"
ssh_key = xobj["#{xpath_context}/SSH_PUBLIC_KEY"]
if ssh_key
cc << "ssh_authorized_keys:\n"
ssh_key.split("\n").each do |key|
cc << "- #{key}\n"
end
end
cc
end
# DEPLOY action, also sets ports and ip if needed
def deploy(id, host, xml_text, lcm_state, deploy_id)
@ -320,17 +355,22 @@ class EC2Driver
# is provided by the user
if !ec2_value(ec2_info, 'USERDATA')
xml = OpenNebula::XMLElement.new
xml.initialize_xml(xml_text, 'VM')
xml.initialize_xml(xml_text, host['PM_MAD'] ? 'HOST' : 'VM')
if xml.has_elements?('TEMPLATE/CONTEXT')
# Since there is only 1 level ',' will not be added
context_str = xml.template_like_str('TEMPLATE/CONTEXT')
# if requested, we generated cloud-init compatible data
if ec2_value(ec2_info, 'CLOUD_INIT') =~ /^(yes|true)$/i
context_str = generate_cc(xml, 'TEMPLATE/CONTEXT')
else
# Since there is only 1 level ',' will not be added
context_str = xml.template_like_str('TEMPLATE/CONTEXT')
if xml['TEMPLATE/CONTEXT/TOKEN'] == 'YES'
# TODO use OneGate library
token_str = generate_onegate_token(xml)
if token_str
context_str << "\nONEGATE_TOKEN=\"#{token_str}\""
if xml['TEMPLATE/CONTEXT/TOKEN'] == 'YES'
# TODO use OneGate library
token_str = generate_onegate_token(xml)
if token_str
context_str << "\nONEGATE_TOKEN=\"#{token_str}\""
end
end
end
@ -386,11 +426,20 @@ class EC2Driver
@ec2.client.associate_address(address)
end
instance.create_tags(tags: [{
key: 'ONE_ID',
value: id
}])
if host['PM_MAD']
instance.create_tags(tags: [{
key: 'Name',
value: host['//HOST/TEMPLATE/PROVISION/HOSTNAME']
},{
key: 'ONE_HOST_ID',
value: 'TODO'
}])
else
instance.create_tags(tags: [{
key: 'ONE_ID',
value: id
}])
end
puts(instance.id)
end
@ -398,21 +447,31 @@ class EC2Driver
# Shutdown a EC2 instance
def shutdown(deploy_id, lcm_state)
case lcm_state
when "SHUTDOWN"
ec2_action(deploy_id, :terminate)
when "SHUTDOWN_POWEROFF", "SHUTDOWN_UNDEPLOY"
ec2_action(deploy_id, :stop)
when "SHUTDOWN"
ec2_action(deploy_id, :terminate)
wait_state('terminated', deploy_id)
when "SHUTDOWN_POWEROFF", "SHUTDOWN_UNDEPLOY"
ec2_action(deploy_id, :stop)
wait_state('stopped', deploy_id)
end
end
# Reboot a EC2 instance
def reboot(deploy_id)
ec2_action(deploy_id, :reboot)
wait_state('running', deploy_id)
end
# Cancel a EC2 instance
def cancel(deploy_id)
ec2_action(deploy_id, :terminate)
def cancel(deploy_id, lcm_state=nil)
case lcm_state
when 'SHUTDOWN_POWEROFF', 'SHUTDOWN_UNDEPLOY'
ec2_action(deploy_id, :stop)
wait_state('stopped', deploy_id)
else
ec2_action(deploy_id, :terminate)
wait_state('terminated', deploy_id)
end
end
# Save a EC2 instance
@ -424,8 +483,17 @@ class EC2Driver
# Resumes a EC2 instance
def restore(deploy_id)
wait_state('stopped', deploy_id)
ec2_action(deploy_id, :start)
wait_state('running', deploy_id)
end
# Resets a EC2 instance
def reset(deploy_id)
ec2_action(deploy_id, :stop)
wait_state('stopped', deploy_id)
ec2_action(deploy_id, :start)
wait_state('running', deploy_id)
end
# Get info (IP, and state) for a EC2 instance
@ -566,7 +634,11 @@ private
ec2 = nil
ec2_deprecated = nil
all_ec2_elements = xml.root.get_elements("//USER_TEMPLATE/PUBLIC_CLOUD")
if host['PM_MAD']
all_ec2_elements = xml.root.get_elements("//TEMPLATE/PROVISION")
else
all_ec2_elements = xml.root.get_elements("//USER_TEMPLATE/PUBLIC_CLOUD")
end
# First, let's see if we have an EC2 site that matches
# our desired host name
@ -590,9 +662,9 @@ private
if all_ec2_elements.size == 1
ec2 = all_ec2_elements[0]
else
raise RuntimeError.new("Cannot find PUBLIC_CLOUD element in deployment "\
" file or no HOST site matching the requested in the "\
" template.")
raise RuntimeError.new("Cannot find PUBLIC_CLOUD element in deployment "\
" file or no HOST site matching the requested in the "\
" template.")
end
end
@ -666,10 +738,10 @@ private
# +ec2_action+: Symbol, one of the keys of the EC2 hash constant (i.e :run)
def ec2_action(deploy_id, ec2_action)
begin
i = get_instance(deploy_id)
i.send(EC2[ec2_action][:cmd])
i = get_instance(deploy_id)
i.send(EC2[ec2_action][:cmd])
rescue => e
raise e
raise e
end
end
@ -721,7 +793,7 @@ private
end
# Waits until ec2 machine reach the desired state
# +state+: String, is the desired state, needs to be a real state of Amazon ec2: running, stopped, terminated, pending
# +state+: String, is the desired state, needs to be a real state of Amazon ec2: running, stopped, terminated, pending
# +deploy_id+: String, VM id in EC2
def wait_state(state, deploy_id)
ready = (state == 'stopped') || (state == 'pending') || (state == 'running') || (state == 'terminated')
@ -927,3 +999,11 @@ private
end
end
def error_message(message)
error_str = "ERROR MESSAGE --8<------\n"
error_str << message
error_str << "\nERROR MESSAGE ------>8--"
return error_str
end