tengine_resource 0.5.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|