lib/kytoon/providers/openstack/server_group.rb in kytoon-1.2.5 vs lib/kytoon/providers/openstack/server_group.rb in kytoon-1.3.0
- old
+ new
@@ -1,8 +1,8 @@
require 'json'
require 'kytoon/util'
-require 'openstack/compute'
+require 'fog'
module Kytoon
module Providers
@@ -24,14 +24,16 @@
CONFIG_FILE = KYTOON_PROJECT + File::SEPARATOR + "config" + File::SEPARATOR + "server_group.json"
attr_accessor :id
attr_accessor :name
+ attr_accessor :use_security_groups
def initialize(options={})
@id = options[:id] || Time.now.to_f
@name = options[:name]
+ @use_security_groups = options[:use_security_groups]
@servers=[]
end
def server(name)
@servers.select {|s| s['hostname'] == name}[0] if @servers.size > 0
@@ -50,21 +52,26 @@
json_hash=JSON.parse(json)
sg=ServerGroup.new(
:id => json_hash["id"],
- :name => json_hash["name"]
+ :name => json_hash["name"],
+ :use_security_groups => json_hash["use_security_groups"]
)
json_hash["servers"].each do |server_hash|
sg.servers << {
'id' => server_hash['id'],
'hostname' => server_hash['hostname'],
'image_ref' => server_hash['image_ref'],
'flavor_ref' => server_hash['flavor_ref'],
'keypair_name' => server_hash['keypair_name'],
+ 'floating_ip' => server_hash['floating_ip'],
'gateway' => server_hash['gateway'] || "false",
+ 'assign_floating_ip' => server_hash['assign_floating_ip'] || "false",
+ 'floating_ip' => server_hash['floating_ip'] || nil,
+ 'floating_ip_id' => server_hash['floating_ip_id'] || nil,
'ip_address' => server_hash['ip_address']
}
end
return sg
end
@@ -82,11 +89,11 @@
end
def server_names
- names=[]
+ names=[]
servers.each do |server|
if block_given? then
yield server['hostname']
else
@@ -101,14 +108,15 @@
def cache_to_disk
sg_hash = {
'id' => @id,
'name' => @name,
+ 'use_security_groups' => @use_security_groups,
'servers' => []
}
@servers.each do |server|
- sg_hash['servers'] << {'id' => server['id'], 'hostname' => server['hostname'], 'image_ref' => server['image_ref'], 'gateway' => server['gateway'], 'flavor_ref' => server['flavor_ref'], 'ip_address' => server['ip_address']}
+ sg_hash['servers'] << {'id' => server['id'], 'hostname' => server['hostname'], 'image_ref' => server['image_ref'], 'gateway' => server['gateway'], 'flavor_ref' => server['flavor_ref'], 'ip_address' => server['ip_address'], 'floating_ip' => server['floating_ip'], 'floating_ip_id' => server['floating_ip_id'], 'assign_floating_ip' => server['assign_floating_ip']}
end
FileUtils.mkdir_p(@@data_dir)
File.open(File.join(@@data_dir, "#{@id}.json"), 'w') do |f|
f.chmod(0600)
@@ -116,57 +124,107 @@
end
end
def delete
servers.each do |server|
+ if server['assign_floating_ip'] == 'true' then
+ ServerGroup.release_floating_ip(server)
+ end
ServerGroup.destroy_instance(server['id'])
end
+
+ #cleanup ssh keys
+ private_ssh_key = File.join(@@data_dir, "#{@id}_id_rsa")
+ public_ssh_key = File.join(@@data_dir, "#{@id}_id_rsa.pub")
+ [private_ssh_key, public_ssh_key].each do |file|
+ File.delete(file) if File.exists?(file)
+ end
+
out_file=File.join(@@data_dir, "#{@id}.json")
File.delete(out_file) if File.exists?(out_file)
end
-
def self.create(sg)
hosts_file_data = "127.0.0.1\tlocalhost localhost.localdomain\n"
build_timeout = (Util.load_configs['openstack_build_timeout'] || 60).to_i
+ base_key_name=File.join(@@data_dir, "#{sg.id}_id_rsa")
+ Kytoon::Util.generate_ssh_keypair(base_key_name)
+ private_ssh_key=IO.read(base_key_name)
+ public_ssh_key=IO.read(base_key_name + ".pub")
+
sg.servers.each do |server|
server_id = create_instance(sg.id, server['hostname'], server['image_ref'], server['flavor_ref'], server['keypair_name']).id
-
server['id'] = server_id
+
+ if server['assign_floating_ip'] == 'true' then
+ floating_data = assign_floating_ip(server_id)
+ server['floating_ip_id'] = floating_data[0]
+ server['floating_ip'] = floating_data[1]
+ end
+
sg.cache_to_disk
end
begin
Timeout::timeout(build_timeout) do
ips = get_server_ips
sg.servers.each do |server|
server_ip = ips[server['id']]
- server['ip_address'] = server_ip
+ if server['assign_floating_ip'] == 'true' then
+ server['ip_address'] = server['floating_ip']
+ else
+ server['ip_address'] = server_ip
+ end
sg.cache_to_disk
hosts_file_data += "#{server_ip}\t#{server['hostname']}\n"
end
end
rescue Timeout::Error => te
raise KytoonException, "Timeout building server group."
end
-
puts "Copying hosts files..."
- #now that we have IP info copy hosts files into the servers
+
+gateway_ssh_config = %{
+[ -d .ssh ] || mkdir .ssh
+cat > .ssh/id_rsa <<-EOF_CAT
+#{private_ssh_key}
+EOF_CAT
+chmod 600 .ssh/id_rsa
+cat > .ssh/id_rsa.pub <<-EOF_CAT
+#{public_ssh_key}
+EOF_CAT
+chmod 600 .ssh/id_rsa.pub
+cat > .ssh/config <<-EOF_CAT
+StrictHostKeyChecking no
+EOF_CAT
+chmod 600 .ssh/config
+}
+
+node_ssh_config= %{
+[ -d .ssh ] || mkdir .ssh
+cat > .ssh/authorized_keys <<-EOF_CAT
+#{public_ssh_key}
+EOF_CAT
+chmod 600 .ssh/authorized_keys
+}
+
+ # now that we have IP info copy hosts files into the servers
sg.servers.each do |server|
ping_test(server['ip_address'])
Kytoon::Util.remote_exec(%{
cat > /etc/hosts <<-EOF_CAT
#{hosts_file_data}
EOF_CAT
hostname "#{server['hostname']}"
if [ -f /etc/sysconfig/network ]; then
sed -e "s|^HOSTNAME.*|HOSTNAME=#{server['hostname']}|" -i /etc/sysconfig/network
fi
+#{server['gateway'] == 'true' ? gateway_ssh_config : node_ssh_config}
}, server['ip_address']) do |ok, out|
if not ok
puts out
raise KytoonException, "Failed to copy host file to instance #{server['hostname']}."
end
@@ -213,43 +271,99 @@
end
def self.init_connection
configs = Util.load_configs
if @@connection.nil? then
- @@connection = OpenStack::Compute::Connection.new(
- :username => configs['openstack_username'].to_s,
- :api_key => configs['openstack_password'].to_s,
- :auth_url => configs['openstack_url'],
- :retry_auth => false)
+ @connection = Fog::Compute.new(
+ :provider => :openstack,
+ :openstack_auth_url => configs['openstack_url'],
+ :openstack_username => configs['openstack_username'],
+ :openstack_api_key => configs['openstack_password'],
+ :openstack_service_name => configs['openstack_service_name'],
+ :openstack_service_type => configs['openstack_service_type'],
+ :openstack_region => configs['openstack_region']
+ )
else
@@connection
end
end
def self.create_instance(group_id, hostname, image_ref, flavor_ref, keypair_name)
- ssh_public_key = Util.public_key_path
configs = Util.load_configs
-
conn = self.init_connection
options = {
:name => "#{group_id}_#{hostname}",
- :imageRef => image_ref,
- :flavorRef => flavor_ref,
- :personality => {ssh_public_key => "/root/.ssh/authorized_keys"},
- :is_debug => true}
+ :image_ref => image_ref,
+ :flavor_ref => flavor_ref}
keypair_name = configs['openstack_keypair_name'] if keypair_name.nil?
+ security_groups = configs['openstack_security_groups']
+ if not security_groups.nil? and not security_groups.empty? then
+ options.store(:security_groups, security_groups)
+ end
if not keypair_name.nil? and not keypair_name.empty? then
options.store(:key_name, keypair_name)
+ else
+ options.store(:personality, [
+ {'path' => "/root/.ssh/authorized_keys",
+ 'contents' => IO.read(Util.public_key_path)}])
end
- conn.create_server(options)
+ server = conn.servers.create(options)
+ server
end
+ def self.assign_floating_ip(server_id)
+
+ conn = self.init_connection
+
+ data = conn.allocate_address.body
+ address_id = data['floating_ip']['id']
+ address_ip = data['floating_ip']['ip']
+
+ configs = Util.load_configs
+ network_name = configs['openstack_network_name'] || 'public'
+
+ # wait for instance to obtain fixed ip
+ 1.upto(60) do
+ server = conn.servers.get(server_id)
+ if server.addresses and server.addresses[network_name] and server.addresses[network_name].detect {|a| a['version'] == self.default_ip_type} then
+ break
+ end
+ end
+
+ conn.associate_address(server_id, address_ip).body
+ [address_id, address_ip]
+
+ end
+
+ def self.release_floating_ip(server)
+
+ conn = self.init_connection
+
+ address_ip = server['floating_ip']
+ address_id = server['floating_ip_id']
+
+ conn.disassociate_address(server['id'], address_ip)
+
+ # wait for address to disassociate (instance_id should be nil)
+ 1.upto(30) do
+ floating_ips = conn.list_all_addresses.body['floating_ips']
+ break if floating_ips.detect {|f| f['id'] == address_id and f['instance_id' == nil]}
+ end
+
+ begin
+ conn.release_address(address_id)
+ rescue Fog::Compute::OpenStack::NotFound
+ puts "Unable to release IP address #{address_ip}: Not Found."
+ end
+
+ end
+
def self.default_ip_type()
ip_type = Util.load_configs['openstack_ip_type'] || 4
ip_type.to_i
end
@@ -263,16 +377,18 @@
conn = self.init_connection
all_active = false
until all_active do
all_active = true
conn.servers.each do |server|
- server = conn.server(server[:id])
- if server.status == 'ACTIVE' and ips[server.id].nil? then
- addresses = server.addresses[network_name.to_sym].select {|a| a.version == self.default_ip_type}
- ips[server.id] = addresses[0].address
- else
- all_active = false
+ if ips[server.id].nil? then
+ server = conn.servers.get(server.id)
+ if server.state == 'ACTIVE' then
+ addresses = server.addresses[network_name].select {|a| a['version'] == self.default_ip_type}
+ ips[server.id] = addresses[0]['addr']
+ else
+ all_active = false
+ end
end
end
end
ips
@@ -300,10 +416,15 @@
end
def self.destroy_instance(uuid)
begin
conn = self.init_connection
- conn.server(uuid).delete!
+ server = conn.servers.get(uuid)
+ if server then
+ server.destroy
+ else
+ puts "Server #{uuid} no longer exists."
+ end
rescue Exception => e
puts "Error deleting server: #{e.message}"
end
end