Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added example to demonstrate executing a command in instance via Delt…

…acloud

git-svn-id: https://svn.apache.org/repos/asf/incubator/deltacloud/trunk@1148758 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information...
commit 6601b874f38295b9ded1b6a590023dc9a9a6505b 1 parent a2246df
@mfojtik mfojtik authored
Showing with 205 additions and 0 deletions.
  1. +205 −0 examples/deltacloud_execute.rb
View
205 examples/deltacloud_execute.rb
@@ -0,0 +1,205 @@
+require 'rubygems'
+require 'colored'
+require 'progress_bar'
+require 'rest-client'
+require 'nokogiri'
+require 'net/ssh'
+require 'net/scp'
+require 'optparse'
+require 'socket'
+require 'timeout'
+
+
+
+options = {}
+optparse = OptionParser.new do |opts|
+ opts.banner = <<BANNER
+Usage:
+cloudexec -f file [options]
+
+Options:
+BANNER
+ opts.on( '-f', '--file FILE', 'Script to execute in instance') { |script| ENV["DC_SCRIPT_NAME"] = script }
+ opts.on( '-d', '--deltacloud-url URL', 'Deltacloud API URL (default: http://localhost:3001/api)') { |script| ENV["DC_URL"] = script }
+ opts.on( '-i', '--image IMAGE', 'Image to use') { |p| ENV["DC_IMAGE"] = p }
+ opts.on( '-u', '--username USERNAME', 'Deltacloud username') { |p| ENV["DC_USERNAME"] = p }
+ opts.on( '-r', '--instance-user USERNAME', 'Instance user. (default: root)') { |p| ENV["DC_INSTANCE_USERNAME"] = p }
+ opts.on( '-p', '--password PASSWORD', 'Deltacloud password') { |p| ENV["DC_PASSWORD"] = p }
+ opts.on( '-s', '--profile HARDWARE_PROFILE', 'Hardware profile to use (default: t1.micro)') { |p| ENV["DC_PROFILE"] = p }
+ opts.on( '-h', '--help', '') { options[:help] = true }
+end
+
+optparse.parse!
+
+if options[:help]
+ puts optparse
+ exit(0)
+end
+
+unless ENV['DC_SCRIPT_NAME']
+ puts "ERROR: You need to specify a script name to be executed on instance".red
+ exit 1
+end
+
+ENV['DC_INSTANCE_USERNAME'] ||= 'ec2-user'
+ENV['DC_URL'] ||= 'http://localhost:5000/api'
+
+config = {
+ :username => ENV['DC_USERNAME'] || '',
+ :password => ENV['DC_PASSWORD'] || '',
+ :image_id => ENV['DC_IMAGE'] || 'ami-8e1fece7',
+ :profile => ENV['DC_PROFILE'] || 't1.micro',
+ :name => "inst-#{Time::now.to_i}"
+}
+
+auth = { :authorization => "Basic " + ["#{config[:username]}:#{config[:password]}"].pack("m0").gsub(/\n/,'') }
+client = RestClient::Resource.new(ENV['DC_URL'])
+
+puts "[INFO] Creating new #{config[:profile]} instance named '#{config[:name]}' using #{config[:image_id]} image...".green
+bar = ProgressBar.new(100, :bar, :percentage)
+
+# Prepare SSH key for instance
+#
+
+# Create SSH key
+key = Nokogiri::XML(client['keys'].post({
+ :name => "key-#{config[:name]}"
+}, auth))
+
+# Save SSH key to local storage
+key_file = File::join("/var/tmp/deltacloud-exec/#{(key/'key/@id')}.pem")
+FileUtils::mkdir_p(File::dirname(key_file))
+File::open(key_file, "w") do |f|
+ (key/'pem').text.split("\n").each do |line|
+ f.puts(line.strip) if line.strip.size > 0
+ end
+end
+FileUtils.chmod 0600, key_file
+bar.increment! 10
+
+#
+#########
+
+# Create new firewall rule for the instance
+#
+
+firewall = client['firewalls'].post({
+ :name => "firewall-#{config[:name]}",
+ :description => "SSH permissive firewall"
+}, auth)
+bar.increment! 10
+
+# Add rule to allow SSH to the firewall
+client["firewalls/firewall-#{config[:name]}/rules"].post({
+ :protocol => 'tcp',
+ :from_port => '22',
+ :to_port => '22',
+ :ip_address => '0.0.0.0/0'
+}, auth)
+bar.increment! 10
+
+#
+########
+
+# Launch instance
+#
+
+instance = client['instances'].post({
+ :name => config[:name],
+ :image_id => config[:image_id],
+ :hwp_id => config[:profile],
+ :keyname => "key-#{config[:name]}",
+ :firewalls1 => "firewall-#{config[:name]}"
+}, auth)
+
+bar.increment! 10
+
+#
+#########
+
+# Pool until instance will be in running state
+
+incrementer = 20
+20.times do
+ instance = client["instances/#{Nokogiri::XML(instance)/'instance/@id'}"].get(auth)
+ bar.increment! 1
+ incrementer -= 1
+ break if (Nokogiri::XML(instance)/'instance/state').first.text == 'RUNNING'
+ sleep(3)
+end
+bar.increment! incrementer
+
+#
+########
+
+# Pool until SSH port is not open
+#
+instance_ip_address = (Nokogiri::XML(instance)/'instance/public_addresses/address').first.text
+incrementer = 20
+20.times do
+ begin
+ Timeout::timeout(1) do
+ begin
+ s = TCPSocket.new(instance_ip_address, 22)
+ s.close
+ break
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
+ sleep(2)
+ bar.increment! 1
+ incrementer -= 1
+ next
+ end
+ end
+ rescue Timeout::Error
+ sleep(2)
+ bar.increment! 1
+ incrementer -= 1
+ end
+end
+bar.increment! incrementer
+
+#########
+
+# Copy script via SCP to the instance
+#
+
+output = ""
+
+Net::SSH.start(instance_ip_address, ENV['DC_INSTANCE_USERNAME'], { :keys => [ key_file ]}) do |session|
+ session.scp.upload! File::expand_path(ENV['DC_SCRIPT_NAME']), "/tmp"
+ output = session.exec!("sh /tmp/#{File::basename(ENV['DC_SCRIPT_NAME'])}")
+end
+
+bar.increment! 20
+
+puts "\t====== OUTPUT ======\n\n#{output}\n\n====================\n"
+puts "[INFO] Cleaning up instance...".green
+
+# Cleanup
+
+bar = ProgressBar.new(100, :bar, :percentage)
+
+result = client["instances/#{(Nokogiri::XML(instance)/'instance/@id').first.text}"].delete(auth)
+if result.status != 204
+ puts "Unable to remove instance #{config[:name]}. Please delete it manually."
+ exit
+else
+ bar.increment! 30
+end
+
+result = client["keys/#{(Nokogiri::XML(key)/'key/@id').first.text}"].delete(auth)
+if result.status != 204
+ puts "Unable to remove key key-#{config[:name]}. Please delete it manually."
+ exit
+else
+ FileUtils.rm key_file
+ bar.increment! 30
+end
+
+result = client["firewalls/#{(Nokogiri::XML(firewall)/'firewall/@id').first.text}"].delete(auth)
+if result.status != 204
+ puts "Unable to remove firewall firewall-#{config[:name]}. Please delete it manually."
+ exit
+else
+ bar.increment! 40
+end
Please sign in to comment.
Something went wrong with that request. Please try again.