tengine_resource 0.5.13
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +30 -0
- data/Gemfile.lock +106 -0
- data/README.rdoc +20 -0
- data/Rakefile +42 -0
- data/VERSION +1 -0
- data/bin/tengine_resource_watchd +8 -0
- data/config/.gitignore +2 -0
- data/config/watchd.yml.erb.example +52 -0
- data/lib/tengine/resource.rb +29 -0
- data/lib/tengine/resource/config.rb +6 -0
- data/lib/tengine/resource/config/resource.rb +194 -0
- data/lib/tengine/resource/credential.rb +156 -0
- data/lib/tengine/resource/credential/ec2.rb +5 -0
- data/lib/tengine/resource/credential/ec2/dummy.rb +148 -0
- data/lib/tengine/resource/credential/ec2/launch_options.rb +179 -0
- data/lib/tengine/resource/drivers/resource_control_driver.rb +58 -0
- data/lib/tengine/resource/net_ssh.rb +134 -0
- data/lib/tengine/resource/observer.rb +25 -0
- data/lib/tengine/resource/physical_server.rb +7 -0
- data/lib/tengine/resource/provider.rb +82 -0
- data/lib/tengine/resource/provider/ec2.rb +187 -0
- data/lib/tengine/resource/provider/wakame.rb +615 -0
- data/lib/tengine/resource/server.rb +62 -0
- data/lib/tengine/resource/virtual_server.rb +62 -0
- data/lib/tengine/resource/virtual_server_image.rb +34 -0
- data/lib/tengine/resource/virtual_server_type.rb +21 -0
- data/lib/tengine/resource/watcher.rb +121 -0
- data/lib/tengine_resource.rb +4 -0
- data/spec/fixtures/goku_at_ec2_ap_northeast.rb +177 -0
- data/spec/mongoid.yml +35 -0
- data/spec/spec_helper.rb +40 -0
- data/spec/support/ec2.rb +129 -0
- data/spec/support/mongo_index_key_log.rb +91 -0
- data/spec/tengine/resource/bugfix/watcher_for_wakame_spec.rb +232 -0
- data/spec/tengine/resource/credential_spec.rb +205 -0
- data/spec/tengine/resource/drivers/resource_control_driver_spec.rb +84 -0
- data/spec/tengine/resource/net_ssh_spec.rb +148 -0
- data/spec/tengine/resource/physical_server_spec.rb +47 -0
- data/spec/tengine/resource/provider/ec2_spec.rb +473 -0
- data/spec/tengine/resource/provider/test_files/describe_host_nodes.json +22 -0
- data/spec/tengine/resource/provider/test_files/describe_images.json +23 -0
- data/spec/tengine/resource/provider/test_files/describe_instance_specs.json +23 -0
- data/spec/tengine/resource/provider/test_files/describe_instances.json +56 -0
- data/spec/tengine/resource/provider/test_files/run_instances.json +30 -0
- data/spec/tengine/resource/provider/test_files/terminate_instances.json +3 -0
- data/spec/tengine/resource/provider/wakame/00_describe_host_nodes_0_physical_servers.json +8 -0
- data/spec/tengine/resource/provider/wakame/01_describe_host_nodes_10_physical_servers.json +139 -0
- data/spec/tengine/resource/provider/wakame/02_describe_host_nodes_60_physical_servers.json +795 -0
- data/spec/tengine/resource/provider/wakame/10_describe_instances_0_virtual_servers.json +8 -0
- data/spec/tengine/resource/provider/wakame/11_describe_instances_10_virtual_servers.json +469 -0
- data/spec/tengine/resource/provider/wakame/12_describe_instances_after_run_instances.json +280 -0
- data/spec/tengine/resource/provider/wakame/13_describe_instances_after_terminate_instances.json +279 -0
- data/spec/tengine/resource/provider/wakame/20_describe_images_0_virtual_server_images.json +8 -0
- data/spec/tengine/resource/provider/wakame/21_describe_images_5_virtual_server_images.json +84 -0
- data/spec/tengine/resource/provider/wakame/22_describe_images_60_virtual_server_images.json +856 -0
- data/spec/tengine/resource/provider/wakame/30_describe_instance_specs_0_virtual_server_specs.json +8 -0
- data/spec/tengine/resource/provider/wakame/31_describe_instance_specs_4_virtual_server_specs.json +66 -0
- data/spec/tengine/resource/provider/wakame/40_run_instances_0_virtual_servers.json +1 -0
- data/spec/tengine/resource/provider/wakame/41_run_instances_1_virtual_servers.json +22 -0
- data/spec/tengine/resource/provider/wakame/42_run_instances_5_virtual_servers.json +106 -0
- data/spec/tengine/resource/provider/wakame/50_terminate_instances_0_virtual_servers.json +1 -0
- data/spec/tengine/resource/provider/wakame/51_terminate_instances_3_virtual_servers.json +5 -0
- data/spec/tengine/resource/provider/wakame/sync_physical_servers_spec.rb +114 -0
- data/spec/tengine/resource/provider/wakame/sync_virtual_server_images_spec.rb +116 -0
- data/spec/tengine/resource/provider/wakame/sync_virtual_server_types_spec.rb +116 -0
- data/spec/tengine/resource/provider/wakame/sync_virtual_servers_spec.rb +216 -0
- data/spec/tengine/resource/provider/wakame_api_spec.rb +319 -0
- data/spec/tengine/resource/provider/wakame_spec.rb +339 -0
- data/spec/tengine/resource/provider_spec.rb +252 -0
- data/spec/tengine/resource/server_spec.rb +195 -0
- data/spec/tengine/resource/test_files/.gitignore +6 -0
- data/spec/tengine/resource/test_files/00_describe_host_nodes_0_physical_servers.json +8 -0
- data/spec/tengine/resource/test_files/01_describe_host_nodes_10_physical_servers.json +139 -0
- data/spec/tengine/resource/test_files/02_describe_host_nodes_60_physical_servers.json +795 -0
- data/spec/tengine/resource/test_files/10_describe_instances_0_virtual_servers.json +8 -0
- data/spec/tengine/resource/test_files/11_describe_instances_10_virtual_servers.json +469 -0
- data/spec/tengine/resource/test_files/12_describe_instances_after_run_instances.json +280 -0
- data/spec/tengine/resource/test_files/13_describe_instances_after_terminate_instances.json +279 -0
- data/spec/tengine/resource/test_files/14_describe_instances_after_run_1_instance.json +55 -0
- data/spec/tengine/resource/test_files/20_describe_images_0_virtual_server_images.json +8 -0
- data/spec/tengine/resource/test_files/21_describe_images_5_virtual_server_images.json +84 -0
- data/spec/tengine/resource/test_files/22_describe_images_60_virtual_server_images.json +856 -0
- data/spec/tengine/resource/test_files/30_describe_instance_specs_0_virtual_server_specs.json +8 -0
- data/spec/tengine/resource/test_files/31_describe_instance_specs_4_virtual_server_specs.json +66 -0
- data/spec/tengine/resource/test_files/40_run_instances_0_virtual_servers.json +1 -0
- data/spec/tengine/resource/test_files/41_run_instances_1_virtual_servers.json +22 -0
- data/spec/tengine/resource/test_files/42_run_instances_5_virtual_servers.json +106 -0
- data/spec/tengine/resource/test_files/43_run_instances_1_virtual_servers_without_aws_availability_zone.json +22 -0
- data/spec/tengine/resource/test_files/50_terminate_instances_0_virtual_servers.json +1 -0
- data/spec/tengine/resource/test_files/51_terminate_instances_3_virtual_servers.json +5 -0
- data/spec/tengine/resource/virtual_server_image_spec.rb +94 -0
- data/spec/tengine/resource/virtual_server_spec.rb +116 -0
- data/spec/tengine/resource/virtual_server_type_spec.rb +4 -0
- data/spec/tengine/resource/watcher_spec.rb +1026 -0
- data/spec/tengine_resource_spec.rb +5 -0
- data/tengine_resource.gemspec +171 -0
- data/tmp/log/.gitignore +1 -0
- metadata +286 -0
@@ -0,0 +1,58 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'active_support/core_ext/hash/keys'
|
3
|
+
|
4
|
+
# リソース制御ドライバ
|
5
|
+
driver :resource_control_driver do
|
6
|
+
|
7
|
+
on :'仮想サーバ起動リクエストイベント' do
|
8
|
+
prop = event.properties.dup
|
9
|
+
|
10
|
+
raise "malformed event (packet corruption?), provider not found. #{event.inspect}" unless pid = prop.delete("provider_id")
|
11
|
+
provider = Tengine::Resource::Provider.find(pid)
|
12
|
+
|
13
|
+
name = provider._type
|
14
|
+
raise "logical bug or DB corruption, unknown class #{name}" unless klass = ObjectSpace.each_object(Class).select {|i| i.name == name }.first
|
15
|
+
|
16
|
+
[["physical_server", Tengine::Resource::PhysicalServer],
|
17
|
+
["virtual_server_image", Tengine::Resource::VirtualServerImage],
|
18
|
+
["virtual_server_type", Tengine::Resource::VirtualServerType],
|
19
|
+
].each do |(i, j)|
|
20
|
+
if k = prop.delete("#{i}_id")
|
21
|
+
prop[i] = j.find(k)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
provider.becomes(klass).create_virtual_servers prop.symbolize_keys
|
26
|
+
end
|
27
|
+
|
28
|
+
on :'仮想サーバ停止リクエストイベント' do
|
29
|
+
prop = event.properties.dup
|
30
|
+
|
31
|
+
raise "malformed event (packet corruption?), provider not found. #{event.inspect}" unless pid = prop.delete("provider_id")
|
32
|
+
provider = Tengine::Resource::Provider.find(pid)
|
33
|
+
|
34
|
+
name = provider._type
|
35
|
+
raise "logical bug or DB corruption, unknown class #{name}" unless klass = ObjectSpace.each_object(Class).select {|i| i.name == name }.first
|
36
|
+
|
37
|
+
raise "malformed event (packet corruption?), no server to stop. #{event.inspect}" unless servers = prop.delete("virtual_servers")
|
38
|
+
|
39
|
+
servers.map! do |i|
|
40
|
+
Tengine::Resource::VirtualServer.find(i)
|
41
|
+
end
|
42
|
+
|
43
|
+
provider.becomes(klass).terminate_virtual_servers servers
|
44
|
+
end
|
45
|
+
|
46
|
+
on :'Tengine::Resource::VirtualServer.created.tengine_resource_watchd' # 仮想サーバ登録通知イベント
|
47
|
+
on :'Tengine::Resource::VirtualServer.updated.tengine_resource_watchd' # 仮想サーバ変更通知イベント
|
48
|
+
on :'Tengine::Resource::VirtualServer.destroyed.tengine_resource_watchd' # 仮想サーバ削除通知イベント
|
49
|
+
on :'Tengine::Resource::PhysicalServer.created.tengine_resource_watchd' # 物理サーバ登録通知イベント
|
50
|
+
on :'Tengine::Resource::PhysicalServer.updated.tengine_resource_watchd' # 物理サーバ変更通知イベント
|
51
|
+
on :'Tengine::Resource::PhysicalServer.destroyed.tengine_resource_watchd' # 物理サーバ削除通知イベント
|
52
|
+
on :'Tengine::Resource::VirtualServerImage.created.tengine_resource_watchd' # 仮想サーバイメージ登録通知イベント
|
53
|
+
on :'Tengine::Resource::VirtualServerImage.updated.tengine_resource_watchd' # 仮想サーバイメージ変更通知イベント
|
54
|
+
on :'Tengine::Resource::VirtualServerImage.destroyed.tengine_resource_watchd' # 仮想サーバイメージ削除通知イベント
|
55
|
+
on :'Tengine::Resource::VirtualServerType.created.tengine_resource_watchd' # 仮想サーバタイプ登録通知イベント
|
56
|
+
on :'Tengine::Resource::VirtualServerType.updated.tengine_resource_watchd' # 仮想サーバタイプ変更通知イベント
|
57
|
+
on :'Tengine::Resource::VirtualServerType.destroyed.tengine_resource_watchd' # 仮想サーバタイプ削除通知イベント
|
58
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'tempfile'
|
3
|
+
require 'net/ssh'
|
4
|
+
require 'active_support/core_ext/hash/keys'
|
5
|
+
|
6
|
+
class << Net::SSH
|
7
|
+
alias __tengine_resource_net_ssh_backed_up_start__ start
|
8
|
+
private :__tengine_resource_net_ssh_backed_up_start__
|
9
|
+
|
10
|
+
# Extended Net::SSH.start
|
11
|
+
#
|
12
|
+
# SYNOPSIS:
|
13
|
+
#
|
14
|
+
# A: Net::SSH.start(hostname, credential) {|ctx| ... }
|
15
|
+
# B: Net::SSH.start(hostname, user, credential) {|ctx| ... }
|
16
|
+
# C: Net::SSH.start(hostname, credential, other_opts) {|ctx| ... }
|
17
|
+
# D: Net::SSH.start(hostname, user, other_opts) {|ctx| ... }
|
18
|
+
# E: Net::SSH.start(hostname, other_opts) {|ctx| ... }
|
19
|
+
#
|
20
|
+
# ARGUMENTS:
|
21
|
+
#
|
22
|
+
# @param [String] hostname Secure Shell host to connect to.
|
23
|
+
# @param [String] user Account to use.
|
24
|
+
# @param [Tengine::Resource::Credential] credential Credential info.
|
25
|
+
# @param [Hash] other_opts Keyword arguments.
|
26
|
+
#
|
27
|
+
# DESCRIPTION:
|
28
|
+
#
|
29
|
+
# Orchestate those given arguments to start SSH connection.
|
30
|
+
#
|
31
|
+
# RETURNS:
|
32
|
+
#
|
33
|
+
# Yields or returns a Net::SSH::Connection.
|
34
|
+
#
|
35
|
+
def start host, obj1, obj2=nil, &block
|
36
|
+
user = nil
|
37
|
+
hash = nil
|
38
|
+
|
39
|
+
case obj1
|
40
|
+
when String
|
41
|
+
user = obj1
|
42
|
+
when Hash
|
43
|
+
hash = obj1.symbolize_keys
|
44
|
+
when Tengine::Resource::Credential
|
45
|
+
hash = obj1.auth_values.symbolize_keys
|
46
|
+
else
|
47
|
+
raise TypeError, "#{obj1.class} not expected (expected String)"
|
48
|
+
end
|
49
|
+
|
50
|
+
hash ||= Hash.new
|
51
|
+
case obj2
|
52
|
+
when NilClass
|
53
|
+
# OK, takes nothing
|
54
|
+
when Hash
|
55
|
+
hash.merge!(obj2.symbolize_keys) {|k, v1, v2|
|
56
|
+
raise ArgumentError, "#{k} specified twice in both credential and hash arguments"
|
57
|
+
}
|
58
|
+
when Tengine::Resource::Credential
|
59
|
+
hash.merge! obj2.auth_values.symbolize_keys {|k, v1, v2|
|
60
|
+
raise ArgumentError, "#{k} specified twice in both credential and hash arguments"
|
61
|
+
}
|
62
|
+
else
|
63
|
+
raise TypeError, "#{obj1.class} not expected (expected #{String})"
|
64
|
+
end
|
65
|
+
|
66
|
+
u2 = hash.delete(:username)
|
67
|
+
k2 = hash.delete(:private_keys)
|
68
|
+
|
69
|
+
raise ArgumentError, "username specified twice in both ordinal and optional arguments" if user and u2
|
70
|
+
user ||= u2
|
71
|
+
raise ArgumentError, "username mandatory" unless user
|
72
|
+
|
73
|
+
argh = %w[
|
74
|
+
auth_methods
|
75
|
+
compression
|
76
|
+
compression_level
|
77
|
+
config
|
78
|
+
encryption
|
79
|
+
forward_agent
|
80
|
+
global_known_hosts_file
|
81
|
+
hmac
|
82
|
+
host_key
|
83
|
+
host_key_alias
|
84
|
+
host_name
|
85
|
+
kex
|
86
|
+
keys
|
87
|
+
key_data
|
88
|
+
keys_only
|
89
|
+
logger
|
90
|
+
paranoid
|
91
|
+
passphrase
|
92
|
+
password
|
93
|
+
port
|
94
|
+
properties
|
95
|
+
proxy
|
96
|
+
rekey_blocks_limit
|
97
|
+
rekey_limit
|
98
|
+
rekey_packet_limit
|
99
|
+
timeout
|
100
|
+
user
|
101
|
+
user_known_hosts_file
|
102
|
+
verbose
|
103
|
+
].map(&:intern).inject(Hash.new) do |r, k|
|
104
|
+
r[k] = hash.delete(k) if hash.has_key? k
|
105
|
+
r
|
106
|
+
end
|
107
|
+
|
108
|
+
raise ArgumentError, "unknown optional argument(s): #{hash.keys.join(', ')}" unless hash.empty?
|
109
|
+
|
110
|
+
if k2
|
111
|
+
k2 = [k2] unless k2.is_a? Array
|
112
|
+
Dir.mktmpdir(nil, File.expand_path("../../../../tmp", __FILE__)) do |dir|
|
113
|
+
begin
|
114
|
+
k3 = k2.map do |k|
|
115
|
+
fp = Tempfile.new("pk", dir)
|
116
|
+
fp.write(k)
|
117
|
+
fp.chmod(0400)
|
118
|
+
fp.flush
|
119
|
+
fp # no close
|
120
|
+
end
|
121
|
+
k4 = k3.map {|i| File.expand_path(i.path) }
|
122
|
+
argh[:keys] ||= []
|
123
|
+
argh[:keys].concat k4
|
124
|
+
|
125
|
+
return __tengine_resource_net_ssh_backed_up_start__ host, user, argh, &block
|
126
|
+
ensure
|
127
|
+
k3.each {|i| i.close(:real) }
|
128
|
+
end
|
129
|
+
end
|
130
|
+
else
|
131
|
+
return __tengine_resource_net_ssh_backed_up_start__ host, user, argh, &block
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'mongoid'
|
3
|
+
|
4
|
+
require 'yaml'
|
5
|
+
require 'tengine_event'
|
6
|
+
require 'tengine/support/yaml_with_erb'
|
7
|
+
|
8
|
+
# http://mongoid.org/docs/callbacks/observers.html
|
9
|
+
class Tengine::Resource::Observer < Mongoid::Observer
|
10
|
+
include Tengine::Event::ModelNotifiable
|
11
|
+
|
12
|
+
prefix = "tengine/resource/"
|
13
|
+
observe *%w[physical_server virtual_server virtual_server_image virtual_server_type].map{|name| :"#{prefix}#{name}" }
|
14
|
+
|
15
|
+
def event_sender
|
16
|
+
@event_sender = Tengine::Event.default_sender
|
17
|
+
end
|
18
|
+
|
19
|
+
SUFFIX = "tengine_resource_watchd".freeze
|
20
|
+
|
21
|
+
def event_type_name_suffix
|
22
|
+
SUFFIX
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
class Tengine::Resource::PhysicalServer < Tengine::Resource::Server
|
2
|
+
field :cpu_cores, :type => Integer
|
3
|
+
field :memory_size, :type => Integer
|
4
|
+
|
5
|
+
belongs_to :provider, :index => true, :inverse_of => :physical_servers,
|
6
|
+
:class_name => "Tengine::Resource::Provider"
|
7
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'mongoid'
|
3
|
+
|
4
|
+
class Tengine::Resource::Provider
|
5
|
+
autoload :Ec2, 'tengine/resource/provider/ec2'
|
6
|
+
autoload :Wakame, 'tengine/resource/provider/wakame'
|
7
|
+
|
8
|
+
include Mongoid::Document
|
9
|
+
include Mongoid::Timestamps
|
10
|
+
include Tengine::Core::Validation
|
11
|
+
include Tengine::Core::FindByName
|
12
|
+
|
13
|
+
field :name, :type => String
|
14
|
+
field :description, :type => String
|
15
|
+
field :polling_interval, :type => Integer, :default => 10 # プロバイダへの問い合わせ間隔
|
16
|
+
field :retry_interval, :type => Integer, :default => 10 # プロバイダへの問い合わせリトライ間隔
|
17
|
+
field :retry_count, :type => Integer, :default => 30 # プロバイダへの問い合わせリトライ回数
|
18
|
+
field :properties, :type => Hash, :default => {}
|
19
|
+
|
20
|
+
validates :name, :presence => true, :uniqueness => true, :format => BASE_NAME.options
|
21
|
+
index :name, :unique => true
|
22
|
+
|
23
|
+
with_options(:inverse_of => :provider, :dependent => :destroy) do |c|
|
24
|
+
c.has_many :physical_servers , :class_name => "Tengine::Resource::PhysicalServer"
|
25
|
+
c.has_many :virtual_servers , :class_name => "Tengine::Resource::VirtualServer"
|
26
|
+
c.has_many :virtual_server_images , :class_name => "Tengine::Resource::VirtualServerImage"
|
27
|
+
c.has_many :virtual_server_types , :class_name => "Tengine::Resource::VirtualServerType"
|
28
|
+
end
|
29
|
+
|
30
|
+
# 仮想サーバタイプの監視
|
31
|
+
def virtual_server_type_watch ; raise NotImplementedError end
|
32
|
+
# 物理サーバの監視
|
33
|
+
def physical_server_watch ; raise NotImplementedError end
|
34
|
+
# 仮想サーバの監視
|
35
|
+
def virtual_server_watch ; raise NotImplementedError end
|
36
|
+
# 仮想サーバイメージの監視
|
37
|
+
def virtual_server_image_watch ; raise NotImplementedError end
|
38
|
+
|
39
|
+
def update_physical_servers ; raise NotImplementedError end
|
40
|
+
def update_virtual_servers ; raise NotImplementedError end
|
41
|
+
def update_virtual_server_imagess; raise NotImplementedError end
|
42
|
+
|
43
|
+
private
|
44
|
+
def update_physical_servers_by(hashs)
|
45
|
+
found_ids = []
|
46
|
+
hashs.each do |hash|
|
47
|
+
server = self.physical_servers.where(:provided_id => hash[:provided_id]).first
|
48
|
+
if server
|
49
|
+
server.update_attributes(:status => hash[:status])
|
50
|
+
else
|
51
|
+
server = self.physical_servers.create!(
|
52
|
+
:provided_id => hash[:provided_id],
|
53
|
+
:name => hash[:name],
|
54
|
+
:status => hash[:status])
|
55
|
+
end
|
56
|
+
found_ids << server.id
|
57
|
+
end
|
58
|
+
self.physical_servers.not_in(:_id => found_ids).update_all(:status => "not_found")
|
59
|
+
end
|
60
|
+
|
61
|
+
def update_virtual_servers_by(hashs)
|
62
|
+
found_ids = []
|
63
|
+
hashs.each do |hash|
|
64
|
+
server = self.virtual_servers.where(:provided_id => hash[:provided_id]).first
|
65
|
+
if server
|
66
|
+
server.update_attributes(hash)
|
67
|
+
else
|
68
|
+
server = self.virtual_servers.create!(hash.merge(:name => hash[:provided_id]))
|
69
|
+
end
|
70
|
+
found_ids << server.id
|
71
|
+
end
|
72
|
+
self.virtual_servers.not_in(:_id => found_ids).destroy_all
|
73
|
+
end
|
74
|
+
|
75
|
+
class << self
|
76
|
+
def find_or_create_by_name!(attrs)
|
77
|
+
result = self.first(:conditions => {:name => attrs[:name]})
|
78
|
+
result ||= self.create!(attrs)
|
79
|
+
result
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
class Tengine::Resource::Provider::Ec2 < Tengine::Resource::Provider
|
3
|
+
|
4
|
+
field :connection_settings, :type => Hash
|
5
|
+
|
6
|
+
def update_physical_servers
|
7
|
+
connect do |conn|
|
8
|
+
# ec2.describe_availability_zones #=> [{:region_name=>"us-east-1",
|
9
|
+
# :zone_name=>"us-east-1a",
|
10
|
+
# :zone_state=>"available"}, ... ]
|
11
|
+
# http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-DescribeAvailabilityZones.html
|
12
|
+
hashs = conn.describe_availability_zones.map do |hash|
|
13
|
+
{
|
14
|
+
:provided_id => hash[:zone_name],
|
15
|
+
:name => hash[:zone_name],
|
16
|
+
:status => hash[:zone_state],
|
17
|
+
}
|
18
|
+
end
|
19
|
+
update_physical_servers_by(hashs)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def update_virtual_servers
|
24
|
+
connect do |conn|
|
25
|
+
# http://rightscale.rubyforge.org/right_aws_gem_doc/
|
26
|
+
# ec2.describe_instances #=>
|
27
|
+
# [{:aws_image_id => "ami-e444444d",
|
28
|
+
# :aws_reason => "",
|
29
|
+
# :aws_state_code => "16",
|
30
|
+
# :aws_owner => "000000000888",
|
31
|
+
# :aws_instance_id => "i-123f1234",
|
32
|
+
# :aws_reservation_id => "r-aabbccdd",
|
33
|
+
# :aws_state => "running",
|
34
|
+
# :dns_name => "domU-12-34-67-89-01-C9.usma2.compute.amazonaws.com",
|
35
|
+
# :ssh_key_name => "staging",
|
36
|
+
# :aws_groups => ["default"],
|
37
|
+
# :private_dns_name => "domU-12-34-67-89-01-C9.usma2.compute.amazonaws.com",
|
38
|
+
# :aws_instance_type => "m1.small",
|
39
|
+
# :aws_launch_time => "2008-1-1T00:00:00.000Z"},
|
40
|
+
# :aws_availability_zone => "us-east-1b",
|
41
|
+
# :aws_kernel_id => "aki-ba3adfd3",
|
42
|
+
# :aws_ramdisk_id => "ari-badbad00",
|
43
|
+
# ..., {...}]
|
44
|
+
# http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-DescribeInstances.html
|
45
|
+
hashs = conn.describe_instances.map do |hash|
|
46
|
+
result = {
|
47
|
+
:provided_id => hash.delete(:aws_instance_id),
|
48
|
+
:provided_image_id => hash.delete(:aws_image_id),
|
49
|
+
:status => hash.delete(:aws_state),
|
50
|
+
}
|
51
|
+
hash.delete(:aws_state_code)
|
52
|
+
result[:properties] = hash
|
53
|
+
result[:addresses] = {
|
54
|
+
:dns_name => hash.delete(:dns_name),
|
55
|
+
:ip_address => hash.delete(:ip_address),
|
56
|
+
:private_dns_name => hash.delete(:private_dns_name),
|
57
|
+
:private_ip_address => hash.delete(:private_ip_address),
|
58
|
+
}
|
59
|
+
result
|
60
|
+
end
|
61
|
+
update_virtual_servers_by(hashs)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def update_virtual_server_images
|
66
|
+
connect do |conn|
|
67
|
+
hashs = conn.describe_images.map do |hash|
|
68
|
+
{ :provided_id => hash.delete(:aws_id), }
|
69
|
+
end
|
70
|
+
update_virtual_server_images_by(hashs)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# @param [String] name Name template for created virtual servers
|
75
|
+
# @param [Tengine::Resource::VirtualServerImage] image Virtual server image object
|
76
|
+
# @param [Tengine::Resource::VirtualServerType] type Virtual server type object
|
77
|
+
# @param [String] physical Data center name to put virtual machines (availability zone)
|
78
|
+
# @param [String] description What this virtual server is
|
79
|
+
# @param [Numeric] min_count Minimum number of vortial servers to boot
|
80
|
+
# @param [Numeric] max_count Maximum number of vortial servers to boot
|
81
|
+
# @param [Array<Strng>] group_ids Array of names of security group IDs
|
82
|
+
# @param [Strng] key_name Name of root key to sue
|
83
|
+
# @param [Strng] user_data User-specified
|
84
|
+
# @param [Strng] kernel_id Kernel image ID
|
85
|
+
# @param [Strng] ramdisk_id Ramdisk image ID
|
86
|
+
# @return [Array<Tengine::Resource::VirtualServer>]
|
87
|
+
def create_virtual_servers name, image, type, physical, description, min_count, max_count, group_ids, key_name, user_data = "", kernel_id, ramdisk_id
|
88
|
+
connect {|conn|
|
89
|
+
results = conn.run_instances(
|
90
|
+
image.provided_id,
|
91
|
+
min_count,
|
92
|
+
max_count,
|
93
|
+
group_ids,
|
94
|
+
key_name,
|
95
|
+
user_data,
|
96
|
+
nil, # <- addressing_type
|
97
|
+
type.provided_id,
|
98
|
+
kernel_id,
|
99
|
+
ramdisk_id,
|
100
|
+
physical,
|
101
|
+
nil # <- block_device_mappings
|
102
|
+
)
|
103
|
+
yield if block_given? # テスト用のブロックの呼び出し
|
104
|
+
results.map.with_index {|hash, idx|
|
105
|
+
provided_id = hash.delete(:aws_instance_id)
|
106
|
+
if server = self.virtual_servers.find(:first, :conditions => {:provided_id => provided_id})
|
107
|
+
server
|
108
|
+
else
|
109
|
+
host_server_provided_id = hash[:aws_availability_zone]
|
110
|
+
host_server_provided_id = physical if host_server_provided_id.nil? || host_server_provided_id.blank?
|
111
|
+
# findではなくfirstで検索しているので、もしhost_server_provided_idで指定されるサーバが見つからなくても
|
112
|
+
# host_serverがnilとして扱われるが、仮想サーバ自身の登録は行われます
|
113
|
+
host_server = (host_server_provided_id && !host_server_provided_id.blank?) ?
|
114
|
+
Tengine::Resource::PhysicalServer.first(:conditions => {:provided_id => host_server_provided_id}) : nil
|
115
|
+
begin
|
116
|
+
self.virtual_servers.create!(
|
117
|
+
:name => sprintf("%s%03d", name, idx + 1), # 1 origin
|
118
|
+
:address_order => address_order,
|
119
|
+
:description => description,
|
120
|
+
:provided_id => provided_id,
|
121
|
+
:provided_image_id => hash.delete(:aws_image_id),
|
122
|
+
:provided_type_id => hash.delete(:aws_instance_type),
|
123
|
+
:host_server_id => host_server ? host_server.id : nil,
|
124
|
+
:status => hash.delete(:aws_state),
|
125
|
+
:properties => hash,
|
126
|
+
:addresses => {
|
127
|
+
# :dns_name => hash.delete(:dns_name),
|
128
|
+
# :ip_address => hash.delete(:ip_address),
|
129
|
+
# :private_dns_name => hash.delete(:private_dns_name),
|
130
|
+
# :private_ip_address => hash.delete(:private_ip_address),
|
131
|
+
})
|
132
|
+
rescue Mongo::OperationFailure => e
|
133
|
+
raise e unless e.message =~ /E11000 duplicate key error/
|
134
|
+
self.virtual_servers.find(:first, :conditions => {:provided_id => provided_id}) or
|
135
|
+
raise "VirtualServer not found for #{provided_id}"
|
136
|
+
rescue Mongoid::Errors::Validations => e
|
137
|
+
raise e unless e.document.errors[:provided_id].any?{|s| s =~ /taken/}
|
138
|
+
self.virtual_servers.find(:first, :conditions => {:provided_id => provided_id}) or
|
139
|
+
raise "VirtualServer not found for #{provided_id}"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
}
|
143
|
+
}
|
144
|
+
end
|
145
|
+
|
146
|
+
def terminate_virtual_servers servers
|
147
|
+
connect do |conn|
|
148
|
+
# http://rightscale.rubyforge.org/right_aws_gem_doc/classes/RightAws/Ec2.html#M000287
|
149
|
+
# http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-TerminateInstances.html
|
150
|
+
conn.terminate_instances(servers.map {|i| i.provided_id }).map do |hash|
|
151
|
+
serv = self.virtual_servers.where(:provided_id => hash[:aws_instance_id]).first
|
152
|
+
serv.update_attributes(:status => hash[:aws_current_state_name]) if serv
|
153
|
+
serv
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# 仮想サーバタイプの監視
|
159
|
+
def virtual_server_type_watch
|
160
|
+
# ec2から取得する情報はありません
|
161
|
+
end
|
162
|
+
|
163
|
+
# 物理サーバの監視
|
164
|
+
def physical_server_watch ; raise NotImplementedError end
|
165
|
+
# 仮想サーバの監視
|
166
|
+
def virtual_server_watch ; raise NotImplementedError end
|
167
|
+
# 仮想サーバイメージの監視
|
168
|
+
def virtual_server_image_watch ; raise NotImplementedError end
|
169
|
+
|
170
|
+
private
|
171
|
+
def address_order
|
172
|
+
@@address_order ||= %w"private_ip_address private_dns_name ip_address dns_name".each(&:freeze).freeze
|
173
|
+
end
|
174
|
+
|
175
|
+
def connect
|
176
|
+
klass = (ENV['EC2_DUMMY'] == "true") ? Tengine::Resource::Credential::Ec2::Dummy : RightAws::Ec2
|
177
|
+
connection = klass.new(
|
178
|
+
self.connection_settings[:access_key],
|
179
|
+
self.connection_settings[:secret_access_key],
|
180
|
+
{
|
181
|
+
:logger => Tengine.logger,
|
182
|
+
:region => self.connection_settings[:region]
|
183
|
+
}
|
184
|
+
)
|
185
|
+
yield connection
|
186
|
+
end
|
187
|
+
end
|