tengine_resource_wakame 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +134 -0
- data/README.rdoc +20 -0
- data/lib/tengine/resource_wakame.rb +6 -0
- data/lib/tengine/resource_wakame/provider.rb +325 -0
- data/lib/tengine/resource_wakame/provider.rb~ +319 -0
- data/lib/tengine_resource_wakame.rb +5 -0
- data/tmp/.gitkeep +0 -0
- metadata +240 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
OTFlYTlhNmRlNTIwOTNkNGJhMDQ3M2M3YjQ3ZjNkZTQ3MjVhMzVkNw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
YjQxZDRkYTFkYjkyOTBjOGI2NTU5YjQwZmM1ZDRmZmQ2NmQwMGRlYQ==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MjU2MDgzNzJjODc4MTU2Y2U2NGI3MjI4ZWYwOTA4ZDI3ZWYyZjY5YTljYzNm
|
10
|
+
YWVlZTFhYTA5MzQwMzBhNjY1OTFiMWM5OWJmOGI1YmQwNDkyMjdkNzY4NWQz
|
11
|
+
OGQ4Y2FjNThhNzkyOGJjNWU3ZjUwZWRlMjQxYmEyNzQ5NjMzN2M=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
N2ZiNGY3YzhjYmI3Njk0ZmZhYzI3ZjkwZDBlNGMxZDFjYjE0NjcwNjRlMjcz
|
14
|
+
OTUyYTczNWZiZWZmNDM3ZWY1YmE2YjAyMGQ3Y2EyYzQ3MGQ0OGUyOTZmNDhl
|
15
|
+
ZTQ5NmJjYjBlOTIxZmQyY2ExZGI2MjViMDQ3NTNmNTljZTJjN2Y=
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
tengine_resource_wakame (1.2.0)
|
5
|
+
tengine_resource (~> 1.2.0)
|
6
|
+
wakame-adapters-tengine (~> 0.0.0)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
ZenTest (4.9.1)
|
12
|
+
activemodel (3.2.12)
|
13
|
+
activesupport (= 3.2.12)
|
14
|
+
builder (~> 3.0.0)
|
15
|
+
activesupport (3.2.12)
|
16
|
+
i18n (~> 0.6)
|
17
|
+
multi_json (~> 1.0)
|
18
|
+
amq-client (0.9.12)
|
19
|
+
amq-protocol (>= 1.2.0)
|
20
|
+
eventmachine
|
21
|
+
amq-protocol (1.2.0)
|
22
|
+
amqp (0.9.10)
|
23
|
+
amq-client (~> 0.9.12)
|
24
|
+
amq-protocol (~> 1.2.0)
|
25
|
+
eventmachine
|
26
|
+
autotest (4.4.6)
|
27
|
+
ZenTest (>= 4.4.1)
|
28
|
+
builder (3.0.4)
|
29
|
+
coderay (1.0.9)
|
30
|
+
columnize (0.3.6)
|
31
|
+
daemons (1.1.9)
|
32
|
+
debugger (1.5.0)
|
33
|
+
columnize (>= 0.3.1)
|
34
|
+
debugger-linecache (~> 1.2.0)
|
35
|
+
debugger-ruby_core_source (~> 1.2.0)
|
36
|
+
debugger-linecache (1.2.0)
|
37
|
+
debugger-ruby_core_source (1.2.0)
|
38
|
+
diff-lcs (1.1.3)
|
39
|
+
eventmachine (1.0.3)
|
40
|
+
i18n (0.6.4)
|
41
|
+
json (1.7.7)
|
42
|
+
macaddr (1.6.1)
|
43
|
+
systemu (~> 2.5.0)
|
44
|
+
method_source (0.8.1)
|
45
|
+
mongoid (3.1.3)
|
46
|
+
activemodel (~> 3.2)
|
47
|
+
moped (~> 1.4.2)
|
48
|
+
origin (~> 1.0)
|
49
|
+
tzinfo (~> 0.3.22)
|
50
|
+
moped (1.4.5)
|
51
|
+
multi_json (1.7.2)
|
52
|
+
net-ssh (2.5.2)
|
53
|
+
origin (1.1.0)
|
54
|
+
pry (0.9.12.1)
|
55
|
+
coderay (~> 1.0.5)
|
56
|
+
method_source (~> 0.8)
|
57
|
+
slop (~> 3.4)
|
58
|
+
pry-debugger (0.2.2)
|
59
|
+
debugger (~> 1.3)
|
60
|
+
pry (~> 0.9.10)
|
61
|
+
pry-doc (0.4.5)
|
62
|
+
pry (>= 0.9)
|
63
|
+
yard (>= 0.8)
|
64
|
+
rake (10.0.4)
|
65
|
+
right_aws (2.1.0)
|
66
|
+
right_http_connection (>= 1.2.5)
|
67
|
+
right_http_connection (1.3.0)
|
68
|
+
rspec (2.10.0)
|
69
|
+
rspec-core (~> 2.10.0)
|
70
|
+
rspec-expectations (~> 2.10.0)
|
71
|
+
rspec-mocks (~> 2.10.0)
|
72
|
+
rspec-core (2.10.1)
|
73
|
+
rspec-expectations (2.10.0)
|
74
|
+
diff-lcs (~> 1.1.3)
|
75
|
+
rspec-mocks (2.10.1)
|
76
|
+
selectable_attr (0.3.17)
|
77
|
+
i18n
|
78
|
+
simplecov (0.7.1)
|
79
|
+
multi_json (~> 1.0)
|
80
|
+
simplecov-html (~> 0.7.1)
|
81
|
+
simplecov-html (0.7.1)
|
82
|
+
slop (3.4.4)
|
83
|
+
systemu (2.5.2)
|
84
|
+
tengine_core (1.2.0)
|
85
|
+
activemodel (>= 3.1.0)
|
86
|
+
activesupport (>= 3.1.0)
|
87
|
+
daemons (~> 1.1.4)
|
88
|
+
mongoid (>= 3.0.22)
|
89
|
+
selectable_attr (~> 0.3.15)
|
90
|
+
tengine_event (~> 1.2.0)
|
91
|
+
tengine_support (~> 1.2.0)
|
92
|
+
tengine_event (1.2.0)
|
93
|
+
activesupport (>= 3.0.0)
|
94
|
+
amqp (~> 0.9.10)
|
95
|
+
tengine_support (~> 1.2.0)
|
96
|
+
uuid (~> 2.3.4)
|
97
|
+
tengine_resource (1.2.0)
|
98
|
+
net-ssh (~> 2.5.2)
|
99
|
+
tengine_core (~> 1.2.0)
|
100
|
+
tengine_support (~> 1.2.0)
|
101
|
+
text-table (~> 1.2.2)
|
102
|
+
thor (>= 0.14.6)
|
103
|
+
tengine_resource_ec2 (1.2.0)
|
104
|
+
right_aws (~> 2.1.0)
|
105
|
+
tengine_resource (~> 1.2.0)
|
106
|
+
tengine_support (1.2.0)
|
107
|
+
activesupport (>= 3.0.0)
|
108
|
+
text-table (1.2.3)
|
109
|
+
thor (0.18.1)
|
110
|
+
tzinfo (0.3.37)
|
111
|
+
uuid (2.3.7)
|
112
|
+
macaddr (~> 1.0)
|
113
|
+
wakame-adapters-tengine (0.0.1)
|
114
|
+
json
|
115
|
+
right_aws (= 2.1.0)
|
116
|
+
rspec
|
117
|
+
yard (0.8.6.1)
|
118
|
+
|
119
|
+
PLATFORMS
|
120
|
+
ruby
|
121
|
+
|
122
|
+
DEPENDENCIES
|
123
|
+
ZenTest (~> 4.9.0)
|
124
|
+
autotest
|
125
|
+
bundler
|
126
|
+
pry
|
127
|
+
pry-debugger
|
128
|
+
pry-doc
|
129
|
+
rake
|
130
|
+
rspec (~> 2.10.0)
|
131
|
+
simplecov
|
132
|
+
tengine_resource_ec2 (~> 1.2.0)
|
133
|
+
tengine_resource_wakame!
|
134
|
+
yard
|
data/README.rdoc
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
= tengine_resource
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
== Contributing to tengine_resource
|
6
|
+
|
7
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
8
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
9
|
+
* Fork the project
|
10
|
+
* Start a feature/bugfix branch
|
11
|
+
* Commit and push until you are happy with your contribution
|
12
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
+
|
15
|
+
== License
|
16
|
+
tengine_resource is distributed under the MPL2.0 or LGPLv3 or the dual license of MPL2.0/LGPLv3
|
17
|
+
|
18
|
+
== Copyright
|
19
|
+
|
20
|
+
Copyright (c) 2012 Groovenauts, Inc.
|
@@ -0,0 +1,325 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'tengine/resource'
|
3
|
+
|
4
|
+
require 'tama'
|
5
|
+
require 'tengine/support/core_ext/hash/keys'
|
6
|
+
require 'tengine/support/core_ext/enumerable/map_to_hash'
|
7
|
+
|
8
|
+
# 1.0.x ではTengine::Resource::Provider::Ec2を継承していましたが、
|
9
|
+
# 1.1.x ではクラス構造を見直して継承する必要はないと判断しTengine::Resource::Providerを継承するように変更しました。
|
10
|
+
class Tengine::ResourceWakame::Provider < Tengine::Resource::Provider
|
11
|
+
|
12
|
+
# モデルの継承時に問題が発生する場合があるので、collectionの呼び出しによる接続先の事前確定を行います。
|
13
|
+
# https://github.com/tengine/tengine/commit/9a986a3b52b18a95b1d5324b9731f720d087d1e4
|
14
|
+
collection
|
15
|
+
|
16
|
+
attr_accessor :retry_on_error
|
17
|
+
|
18
|
+
field :connection_settings, :type => Hash
|
19
|
+
|
20
|
+
PHYSICAL_SERVER_STATES = [:online, :offline].freeze
|
21
|
+
|
22
|
+
VIRTUAL_SERVER_STATES = [
|
23
|
+
:scheduling, :pending, :starting, :running,
|
24
|
+
:failingover, :shuttingdown, :terminated].freeze
|
25
|
+
|
26
|
+
# @param [String] name Name template for created virtual servers
|
27
|
+
# @param [Tengine::Resource::VirtualServerImage] image Virtual server image object
|
28
|
+
# @param [Tengine::Resource::VirtualServerType] type Virtual server type object
|
29
|
+
# @param [String] physical Data center name to put virtual machines (availability zone)
|
30
|
+
# @param [String] description What this virtual server is
|
31
|
+
# @param [Numeric] count number of vortial servers to boot
|
32
|
+
# @return [Array<Tengine::Resource::VirtualServer>]
|
33
|
+
def create_virtual_servers(name, image, type, physical, description = "", count = 1)
|
34
|
+
physical_provided_id = physical.respond_to?(:provided_id) ? physical.provided_id : physical
|
35
|
+
connect {|conn|
|
36
|
+
results = conn.run_instances(
|
37
|
+
image.provided_id,
|
38
|
+
count,
|
39
|
+
count,
|
40
|
+
[],
|
41
|
+
self.properties['key_name'] || self.properties[:key_name],
|
42
|
+
"",
|
43
|
+
nil, # <- addressing_type
|
44
|
+
type.provided_id,
|
45
|
+
nil,
|
46
|
+
nil,
|
47
|
+
physical_provided_id,
|
48
|
+
nil # <- block_device_mappings
|
49
|
+
)
|
50
|
+
yield if block_given? # テスト用のブロックの呼び出し
|
51
|
+
results.map.with_index {|hash, idx|
|
52
|
+
provided_id = hash.delete(:aws_instance_id)
|
53
|
+
if server = self.virtual_servers.where({:provided_id => provided_id}).first
|
54
|
+
server
|
55
|
+
else
|
56
|
+
# findではなくfirstで検索しているので、もしhost_server_provided_idで指定されるサーバが見つからなくても
|
57
|
+
# host_serverがnilとして扱われるが、仮想サーバ自身の登録は行われます
|
58
|
+
host_server = Tengine::Resource::PhysicalServer.by_provided_id(
|
59
|
+
[hash[:aws_availability_zone], physical_provided_id].detect{|i| !i.blank?})
|
60
|
+
self.find_virtual_server_on_duplicaion_error(provided_id) do
|
61
|
+
self.virtual_servers.create!(
|
62
|
+
:name => sprintf("%s%03d", name, idx + 1), # 1 origin
|
63
|
+
:address_order => address_order.dup,
|
64
|
+
:description => description,
|
65
|
+
:provided_id => provided_id,
|
66
|
+
:provided_image_id => hash.delete(:aws_image_id),
|
67
|
+
:provided_type_id => hash.delete(:aws_instance_type),
|
68
|
+
:host_server_id => host_server ? host_server.id : nil,
|
69
|
+
:status => hash.delete(:aws_state),
|
70
|
+
:properties => hash,
|
71
|
+
:addresses => {
|
72
|
+
# :dns_name => hash.delete(:dns_name),
|
73
|
+
# :ip_address => hash.delete(:ip_address),
|
74
|
+
# :private_dns_name => hash.delete(:private_dns_name),
|
75
|
+
# :private_ip_address => hash.delete(:private_ip_address),
|
76
|
+
})
|
77
|
+
end
|
78
|
+
end
|
79
|
+
}
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
def terminate_virtual_servers(servers)
|
85
|
+
connect do |conn|
|
86
|
+
conn.terminate_instances(servers.map {|i| i.provided_id }).map do |hash|
|
87
|
+
serv = self.virtual_servers.where(:provided_id => hash[:aws_instance_id]).first
|
88
|
+
serv
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def capacities(keep_cache = false)
|
94
|
+
reload unless keep_cache
|
95
|
+
server_type_ids = virtual_server_types.map(&:provided_id)
|
96
|
+
server_type_to_cpu = virtual_server_types.map_to_hash(:provided_id, &:cpu_cores)
|
97
|
+
server_type_to_mem = virtual_server_types.map_to_hash(:provided_id, &:memory_size)
|
98
|
+
physical_servers.inject({}) do |result, physical_server|
|
99
|
+
if physical_server.status == 'online'
|
100
|
+
active_guests = physical_server.guest_servers.reject do |i|
|
101
|
+
i.status.to_s == "terminated" or
|
102
|
+
server_type_to_cpu[i.provided_type_id].nil? or
|
103
|
+
server_type_to_mem[i.provided_type_id].nil?
|
104
|
+
end
|
105
|
+
cpu_free = physical_server.cpu_cores - active_guests.map{|s| server_type_to_cpu[s.provided_type_id]}.sum
|
106
|
+
mem_free = physical_server.memory_size - active_guests.map{|s| server_type_to_mem[s.provided_type_id]}.sum
|
107
|
+
result[physical_server.provided_id] = server_type_ids.map_to_hash do |server_type_id|
|
108
|
+
[ cpu_free / server_type_to_cpu[server_type_id],
|
109
|
+
mem_free / server_type_to_mem[server_type_id]
|
110
|
+
].min
|
111
|
+
end
|
112
|
+
else
|
113
|
+
result[physical_server.provided_id] = server_type_ids.map_to_hash{|server_type_id| 0}
|
114
|
+
end
|
115
|
+
result
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def synchronize_physical_servers ; synchronize_by(:physical_servers ); end # 物理サーバの監視
|
120
|
+
def synchronize_virtual_server_types ; synchronize_by(:virtual_server_types ); end # 仮想サーバタイプの監視
|
121
|
+
def synchronize_virtual_server_images; synchronize_by(:virtual_server_images); end # 仮想サーバイメージの監視
|
122
|
+
def synchronize_virtual_servers ; synchronize_by(:virtual_servers ); end # 仮想サーバの監視
|
123
|
+
|
124
|
+
# wakame api for tama
|
125
|
+
def describe_instance_specs_for_api(uuids = [], options = {})
|
126
|
+
call_api_with_conversion(:describe_instance_specs, uuids, options)
|
127
|
+
end
|
128
|
+
|
129
|
+
def describe_host_nodes_for_api(uuids = [], options = {})
|
130
|
+
call_api_with_conversion(:describe_host_nodes, uuids, options)
|
131
|
+
end
|
132
|
+
|
133
|
+
def describe_instances_for_api(uuids = [], options = {})
|
134
|
+
result = call_api_with_conversion(:describe_instances, uuids, options)
|
135
|
+
result.each do |r|
|
136
|
+
replace_value_of_hash(r, :private_ip_address) do |v|
|
137
|
+
v.first if v.is_a?(Array)
|
138
|
+
end
|
139
|
+
replace_value_of_hash(r, :ip_address) do |v|
|
140
|
+
"nw-data\=#{$1}" if (v =~ /^nw\-data\=\[\"(.+)\"\]$/)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
result
|
144
|
+
end
|
145
|
+
|
146
|
+
def describe_images_for_api(uuids = [], options = {})
|
147
|
+
call_api_with_conversion(:describe_images, uuids, options)
|
148
|
+
end
|
149
|
+
|
150
|
+
def run_instances_for_api(uuids = [], options = {})
|
151
|
+
call_api_with_conversion(:run_instances, uuids, options)
|
152
|
+
end
|
153
|
+
|
154
|
+
def terminate_instances_for_api(uuids = [], options = {})
|
155
|
+
call_api_with_conversion(:terminate_instances, uuids, options)
|
156
|
+
end
|
157
|
+
|
158
|
+
private
|
159
|
+
|
160
|
+
# wakame api からの戻り値がのキーが文字列だったりシンボルだったりで統一されてないので暫定対応で
|
161
|
+
# 戻り値の配列の要素となるHashのkeyをstringかsymbolかのどちらかに指定できるようにしています
|
162
|
+
def call_api_with_conversion(api_name, uuids, options)
|
163
|
+
result = connect{|conn| conn.send(api_name, uuids) }
|
164
|
+
case options[:convert]
|
165
|
+
when :string then result.map(&:deep_stringify_keys!)
|
166
|
+
when :symbol then result.map(&:deep_symbolize_keys!)
|
167
|
+
else result
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def replace_value_of_hash(hash, key)
|
172
|
+
[key, key.to_s].each do |k|
|
173
|
+
if value = hash[k]
|
174
|
+
if result = yield(value)
|
175
|
+
hash[k] = result
|
176
|
+
return
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
public
|
183
|
+
|
184
|
+
def connect(&block)
|
185
|
+
send(retry_on_error ? :connect_with_retry : :connect_without_retry, &block)
|
186
|
+
end
|
187
|
+
|
188
|
+
CONNECTION_TEST_ATTRIBUTES = [:describe_instances_file, :describe_images_file, :run_instances_file,
|
189
|
+
:terminate_instances_file, :describe_host_nodes_file, :describe_instance_specs_file].freeze
|
190
|
+
|
191
|
+
def connect_without_retry
|
192
|
+
connection = nil
|
193
|
+
if self.connection_settings[:test] || self.connection_settings["test"]
|
194
|
+
# テスト用
|
195
|
+
connection = ::Tama::Controllers::ControllerFactory.create_controller(:test)
|
196
|
+
options = self.connection_settings[:options] || self.connection_settings["options"]
|
197
|
+
if options
|
198
|
+
options.symbolize_keys!
|
199
|
+
CONNECTION_TEST_ATTRIBUTES.each do |key|
|
200
|
+
connection.send("#{key}=", File.expand_path(options[key])) if options[key]
|
201
|
+
end
|
202
|
+
end
|
203
|
+
else
|
204
|
+
options = self.connection_settings.symbolize_keys
|
205
|
+
args = [:account, :ec2_host, :ec2_port, :ec2_protocol, :wakame_host, :wakame_port, :wakame_protocol].map{|key| options[key]}
|
206
|
+
connection = ::Tama::Controllers::ControllerFactory.create_controller(*args)
|
207
|
+
end
|
208
|
+
return yield(connection)
|
209
|
+
end
|
210
|
+
|
211
|
+
def connect_with_retry(&block)
|
212
|
+
retry_count = 1
|
213
|
+
begin
|
214
|
+
return connect_without_retry(&block)
|
215
|
+
rescue Exception => e
|
216
|
+
if retry_count > self.retry_count
|
217
|
+
Tengine.logger.error "#{e.class.name} #{e.message}"
|
218
|
+
raise e
|
219
|
+
else
|
220
|
+
Tengine.logger.warn "retry[#{retry_count}]: #{e.message}"
|
221
|
+
sleep self.retry_interval
|
222
|
+
retry_count += 1
|
223
|
+
retry
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
private
|
229
|
+
|
230
|
+
def address_order
|
231
|
+
@@address_order ||= ['private_ip_address'.freeze].freeze
|
232
|
+
end
|
233
|
+
|
234
|
+
public
|
235
|
+
|
236
|
+
class Synchronizer < Tengine::Resource::Provider::Synchronizer
|
237
|
+
end
|
238
|
+
|
239
|
+
class PhysicalServerSynchronizer < Synchronizer
|
240
|
+
fetch_known_target_method :describe_host_nodes_for_api
|
241
|
+
|
242
|
+
map(:provided_id, :id)
|
243
|
+
# wakame-adapters-tengine が name を返さない仕様の場合は、provided_id を name に登録します
|
244
|
+
map(:name){|hash, _| hash.delete(:name) || hash[:id]}
|
245
|
+
map(:status , :status)
|
246
|
+
map(:cpu_cores , :offering_cpu_cores)
|
247
|
+
map(:memory_size, :offering_memory_size)
|
248
|
+
end
|
249
|
+
|
250
|
+
class VirtualServerTypeSynchronizer < Synchronizer
|
251
|
+
fetch_known_target_method :describe_instance_specs_for_api
|
252
|
+
|
253
|
+
map :provided_id, :id
|
254
|
+
map :caption , :uuid
|
255
|
+
map :cpu_cores , :cpu_cores
|
256
|
+
map :memory_size, :memory_size
|
257
|
+
end
|
258
|
+
|
259
|
+
class VirtualServerImageSynchronizer < Synchronizer
|
260
|
+
fetch_known_target_method :describe_images_for_api
|
261
|
+
|
262
|
+
map :provided_id , :aws_id
|
263
|
+
map :provided_description, :description
|
264
|
+
|
265
|
+
def attrs_to_create(properties)
|
266
|
+
result = super(properties)
|
267
|
+
# 初期登録時、default 値として name には一意な provided_id を name へ登録します
|
268
|
+
result[:name] = result[:provided_id]
|
269
|
+
result
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
class VirtualServerSynchronizer < Synchronizer
|
274
|
+
fetch_known_target_method :describe_instances_for_api
|
275
|
+
|
276
|
+
PRIVATE_IP_ADDRESS = "private_ip_address".freeze
|
277
|
+
|
278
|
+
map(:provided_id , :aws_instance_id)
|
279
|
+
map(:provided_image_id, :aws_image_id)
|
280
|
+
map(:provided_type_id , :aws_instance_type)
|
281
|
+
map(:status , :aws_state)
|
282
|
+
map(:host_server) do |props, provider|
|
283
|
+
provider.physical_servers.where(:provided_id => props[:aws_availability_zone]).first
|
284
|
+
end
|
285
|
+
map(:addresses) do|props, _|
|
286
|
+
result = { PRIVATE_IP_ADDRESS => props.delete(:private_ip_address) }
|
287
|
+
props.delete(:ip_address).split(",").map do |i|
|
288
|
+
k, v = *i.split("=", 2)
|
289
|
+
result[k] = v
|
290
|
+
end
|
291
|
+
result
|
292
|
+
end
|
293
|
+
|
294
|
+
def create_by_hash(hash)
|
295
|
+
super(hash)
|
296
|
+
rescue Mongo::OperationFailure => e
|
297
|
+
raise e unless e.message =~ /E11000 duplicate key error/
|
298
|
+
nil
|
299
|
+
rescue Mongoid::Errors::Validations => e
|
300
|
+
raise e unless e.document.errors[:provided_id].any?{|s| s =~ /taken/}
|
301
|
+
nil
|
302
|
+
end
|
303
|
+
|
304
|
+
def attrs_to_create(properties)
|
305
|
+
result = super(properties)
|
306
|
+
# 初期登録時、default 値として name には一意な provided_id を name へ登録します
|
307
|
+
result[:name] = result[:provided_id]
|
308
|
+
result
|
309
|
+
end
|
310
|
+
|
311
|
+
def differential_update_by_hash(hash)
|
312
|
+
super(hash) do |virtual_server, properties|
|
313
|
+
virtual_server.save! if virtual_server.changed? && !virtual_server.changes.values.all?{|v| v.nil?}
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
register_synchronizers({
|
319
|
+
:physical_servers => PhysicalServerSynchronizer,
|
320
|
+
:virtual_server_types => VirtualServerTypeSynchronizer,
|
321
|
+
:virtual_server_images => VirtualServerImageSynchronizer,
|
322
|
+
:virtual_servers => VirtualServerSynchronizer,
|
323
|
+
})
|
324
|
+
|
325
|
+
end
|
@@ -0,0 +1,319 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'tengine_resource'
|
3
|
+
require 'tengine/resource/provider/ec2'
|
4
|
+
|
5
|
+
require 'tama'
|
6
|
+
require 'tengine/support/core_ext/hash/keys'
|
7
|
+
require 'tengine/support/core_ext/enumerable/map_to_hash'
|
8
|
+
|
9
|
+
|
10
|
+
class Tengine::Resource::Provider::Wakame < Tengine::Resource::Provider::Ec2
|
11
|
+
|
12
|
+
attr_accessor :retry_on_error
|
13
|
+
|
14
|
+
# field :connection_settings, :type => Hash # 継承元のTengine::Resource::Provider::Ec2で定義されているので不要
|
15
|
+
|
16
|
+
PHYSICAL_SERVER_STATES = [:online, :offline].freeze
|
17
|
+
|
18
|
+
VIRTUAL_SERVER_STATES = [
|
19
|
+
:scheduling, :pending, :starting, :running,
|
20
|
+
:failingover, :shuttingdown, :terminated].freeze
|
21
|
+
|
22
|
+
def update_virtual_server_images
|
23
|
+
connect do |conn|
|
24
|
+
hashs = conn.describe_images.map do |hash|
|
25
|
+
{
|
26
|
+
:provided_id => hash.delete(:aws_id),
|
27
|
+
:provided_description => hash.delete(:aws_description),
|
28
|
+
}
|
29
|
+
end
|
30
|
+
update_virtual_server_images_by(hashs)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# @param [String] name Name template for created virtual servers
|
35
|
+
# @param [Tengine::Resource::VirtualServerImage] image virtual server image object
|
36
|
+
# @param [Tengine::Resource::VirtualServerType] type virtual server type object
|
37
|
+
# @param [Tengine::Resource::PhysicalServer] physical physical server object
|
38
|
+
# @param [String] description what this virtual server is
|
39
|
+
# @param [Numeric] count number of vortial servers to boot
|
40
|
+
# @return [Array<Tengine::Resource::VirtualServer>]
|
41
|
+
def create_virtual_servers(name, image, type, physical, description = "", count = 1, &block)
|
42
|
+
return super(
|
43
|
+
name,
|
44
|
+
image,
|
45
|
+
type,
|
46
|
+
physical.provided_id,
|
47
|
+
description,
|
48
|
+
count, # min
|
49
|
+
count, # max
|
50
|
+
[], # grouop id
|
51
|
+
self.properties['key_name'] || self.properties[:key_name],
|
52
|
+
"", # user data
|
53
|
+
nil, # kernel id
|
54
|
+
nil, # ramdisk id
|
55
|
+
&block
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
def terminate_virtual_servers(servers)
|
60
|
+
connect do |conn|
|
61
|
+
conn.terminate_instances(servers.map {|i| i.provided_id }).map do |hash|
|
62
|
+
serv = self.virtual_servers.where(:provided_id => hash[:aws_instance_id]).first
|
63
|
+
serv
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def capacities(keep_cache = false)
|
69
|
+
reload unless keep_cache
|
70
|
+
server_type_ids = virtual_server_types.map(&:provided_id)
|
71
|
+
server_type_to_cpu = virtual_server_types.map_to_hash(:provided_id, &:cpu_cores)
|
72
|
+
server_type_to_mem = virtual_server_types.map_to_hash(:provided_id, &:memory_size)
|
73
|
+
physical_servers.inject({}) do |result, physical_server|
|
74
|
+
if physical_server.status == 'online'
|
75
|
+
active_guests = physical_server.guest_servers.reject do |i|
|
76
|
+
i.status.to_s == "terminated" or
|
77
|
+
server_type_to_cpu[i.provided_type_id].nil? or
|
78
|
+
server_type_to_mem[i.provided_type_id].nil?
|
79
|
+
end
|
80
|
+
cpu_free = physical_server.cpu_cores - active_guests.map{|s| server_type_to_cpu[s.provided_type_id]}.sum
|
81
|
+
mem_free = physical_server.memory_size - active_guests.map{|s| server_type_to_mem[s.provided_type_id]}.sum
|
82
|
+
result[physical_server.provided_id] = server_type_ids.map_to_hash do |server_type_id|
|
83
|
+
[ cpu_free / server_type_to_cpu[server_type_id],
|
84
|
+
mem_free / server_type_to_mem[server_type_id]
|
85
|
+
].min
|
86
|
+
end
|
87
|
+
else
|
88
|
+
result[physical_server.provided_id] = server_type_ids.map_to_hash{|server_type_id| 0}
|
89
|
+
end
|
90
|
+
result
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def synchronize_physical_servers ; synchronize_by(:physical_servers ); end # 物理サーバの監視
|
95
|
+
def synchronize_virtual_server_types ; synchronize_by(:virtual_server_types ); end # 仮想サーバタイプの監視
|
96
|
+
def synchronize_virtual_server_images; synchronize_by(:virtual_server_images); end # 仮想サーバイメージの監視
|
97
|
+
def synchronize_virtual_servers ; synchronize_by(:virtual_servers ); end # 仮想サーバの監視
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def synchronize_by(target_name)
|
102
|
+
synchronizer = synchronizers_by(target_name)
|
103
|
+
synchronizer.execute
|
104
|
+
end
|
105
|
+
|
106
|
+
def synchronizers_by(target_name)
|
107
|
+
unless @synchronizers
|
108
|
+
@synchronizers = {}
|
109
|
+
SYNCHRONIZER_CLASSES.each do |target_name, klass|
|
110
|
+
@synchronizers[target_name] = klass.new(self, target_name)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
@synchronizers[target_name]
|
114
|
+
end
|
115
|
+
|
116
|
+
public
|
117
|
+
|
118
|
+
# wakame api for tama
|
119
|
+
def describe_instance_specs_for_api(uuids = [], options = {})
|
120
|
+
call_api_with_conversion(:describe_instance_specs, uuids, options)
|
121
|
+
end
|
122
|
+
|
123
|
+
def describe_host_nodes_for_api(uuids = [], options = {})
|
124
|
+
call_api_with_conversion(:describe_host_nodes, uuids, options)
|
125
|
+
end
|
126
|
+
|
127
|
+
def describe_instances_for_api(uuids = [], options = {})
|
128
|
+
result = call_api_with_conversion(:describe_instances, uuids, options)
|
129
|
+
result.each do |r|
|
130
|
+
replace_value_of_hash(r, :private_ip_address) do |v|
|
131
|
+
v.first if v.is_a?(Array)
|
132
|
+
end
|
133
|
+
replace_value_of_hash(r, :ip_address) do |v|
|
134
|
+
"nw-data\=#{$1}" if (v =~ /^nw\-data\=\[\"(.+)\"\]$/)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
result
|
138
|
+
end
|
139
|
+
|
140
|
+
def describe_images_for_api(uuids = [], options = {})
|
141
|
+
call_api_with_conversion(:describe_images, uuids, options)
|
142
|
+
end
|
143
|
+
|
144
|
+
def run_instances_for_api(uuids = [], options = {})
|
145
|
+
call_api_with_conversion(:run_instances, uuids, options)
|
146
|
+
end
|
147
|
+
|
148
|
+
def terminate_instances_for_api(uuids = [], options = {})
|
149
|
+
call_api_with_conversion(:terminate_instances, uuids, options)
|
150
|
+
end
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
# wakame api からの戻り値がのキーが文字列だったりシンボルだったりで統一されてないので暫定対応で
|
155
|
+
# 戻り値の配列の要素となるHashのkeyをstringかsymbolかのどちらかに指定できるようにしています
|
156
|
+
def call_api_with_conversion(api_name, uuids, options)
|
157
|
+
result = connect{|conn| conn.send(api_name, uuids) }
|
158
|
+
case options[:convert]
|
159
|
+
when :string then result.map(&:deep_stringify_keys!)
|
160
|
+
when :symbol then result.map(&:deep_symbolize_keys!)
|
161
|
+
else result
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def replace_value_of_hash(hash, key)
|
166
|
+
[key, key.to_s].each do |k|
|
167
|
+
if value = hash[k]
|
168
|
+
if result = yield(value)
|
169
|
+
hash[k] = result
|
170
|
+
return
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
public
|
177
|
+
|
178
|
+
def connect(&block)
|
179
|
+
send(retry_on_error ? :connect_with_retry : :connect_without_retry, &block)
|
180
|
+
end
|
181
|
+
|
182
|
+
CONNECTION_TEST_ATTRIBUTES = [:describe_instances_file, :describe_images_file, :run_instances_file,
|
183
|
+
:terminate_instances_file, :describe_host_nodes_file, :describe_instance_specs_file].freeze
|
184
|
+
|
185
|
+
def connect_without_retry
|
186
|
+
connection = nil
|
187
|
+
if self.connection_settings[:test] || self.connection_settings["test"]
|
188
|
+
# テスト用
|
189
|
+
connection = ::Tama::Controllers::ControllerFactory.create_controller(:test)
|
190
|
+
options = self.connection_settings[:options] || self.connection_settings["options"]
|
191
|
+
if options
|
192
|
+
options.symbolize_keys!
|
193
|
+
CONNECTION_TEST_ATTRIBUTES.each do |key|
|
194
|
+
connection.send("#{key}=", File.expand_path(options[key])) if options[key]
|
195
|
+
end
|
196
|
+
end
|
197
|
+
else
|
198
|
+
options = self.connection_settings.symbolize_keys
|
199
|
+
args = [:account, :ec2_host, :ec2_port, :ec2_protocol, :wakame_host, :wakame_port, :wakame_protocol].map{|key| options[key]}
|
200
|
+
connection = ::Tama::Controllers::ControllerFactory.create_controller(*args)
|
201
|
+
end
|
202
|
+
return yield(connection)
|
203
|
+
end
|
204
|
+
|
205
|
+
def connect_with_retry(&block)
|
206
|
+
retry_count = 1
|
207
|
+
begin
|
208
|
+
return connect_without_retry(&block)
|
209
|
+
rescue Exception => e
|
210
|
+
if retry_count > self.retry_count
|
211
|
+
Tengine.logger.error "#{e.class.name} #{e.message}"
|
212
|
+
raise e
|
213
|
+
else
|
214
|
+
Tengine.logger.warn "retry[#{retry_count}]: #{e.message}"
|
215
|
+
sleep self.retry_interval
|
216
|
+
retry_count += 1
|
217
|
+
retry
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
private
|
223
|
+
|
224
|
+
def address_order
|
225
|
+
@@address_order ||= ['private_ip_address'.freeze].freeze
|
226
|
+
end
|
227
|
+
|
228
|
+
public
|
229
|
+
|
230
|
+
class Synchronizer < Tengine::Resource::Provider::Synchronizer
|
231
|
+
end
|
232
|
+
|
233
|
+
class PhysicalServerSynchronizer < Synchronizer
|
234
|
+
fetch_known_target_method :describe_host_nodes_for_api
|
235
|
+
|
236
|
+
map(:provided_id, :id)
|
237
|
+
# wakame-adapters-tengine が name を返さない仕様の場合は、provided_id を name に登録します
|
238
|
+
map(:name){|hash, _| hash.delete(:name) || hash[:id]}
|
239
|
+
map(:status , :status)
|
240
|
+
map(:cpu_cores , :offering_cpu_cores)
|
241
|
+
map(:memory_size, :offering_memory_size)
|
242
|
+
end
|
243
|
+
|
244
|
+
class VirtualServerTypeSynchronizer < Synchronizer
|
245
|
+
fetch_known_target_method :describe_instance_specs_for_api
|
246
|
+
|
247
|
+
map :provided_id, :id
|
248
|
+
map :caption , :uuid
|
249
|
+
map :cpu_cores , :cpu_cores
|
250
|
+
map :memory_size, :memory_size
|
251
|
+
end
|
252
|
+
|
253
|
+
class VirtualServerImageSynchronizer < Synchronizer
|
254
|
+
fetch_known_target_method :describe_images_for_api
|
255
|
+
|
256
|
+
map :provided_id , :aws_id
|
257
|
+
map :provided_description, :description
|
258
|
+
|
259
|
+
def attrs_to_create(properties)
|
260
|
+
result = super(properties)
|
261
|
+
# 初期登録時、default 値として name には一意な provided_id を name へ登録します
|
262
|
+
result[:name] = result[:provided_id]
|
263
|
+
result
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
class VirtualServerSynchronizer < Synchronizer
|
268
|
+
fetch_known_target_method :describe_instances_for_api
|
269
|
+
|
270
|
+
PRIVATE_IP_ADDRESS = "private_ip_address".freeze
|
271
|
+
|
272
|
+
map(:provided_id , :aws_instance_id)
|
273
|
+
map(:provided_image_id, :aws_image_id)
|
274
|
+
map(:provided_type_id , :aws_instance_type)
|
275
|
+
map(:status , :aws_state)
|
276
|
+
map(:host_server) do |props, provider|
|
277
|
+
provider.physical_servers.where(:provided_id => props[:aws_availability_zone]).first
|
278
|
+
end
|
279
|
+
map(:addresses) do|props, _|
|
280
|
+
result = { PRIVATE_IP_ADDRESS => props.delete(:private_ip_address) }
|
281
|
+
props.delete(:ip_address).split(",").map do |i|
|
282
|
+
k, v = *i.split("=", 2)
|
283
|
+
result[k] = v
|
284
|
+
end
|
285
|
+
result
|
286
|
+
end
|
287
|
+
|
288
|
+
def create_by_hash(hash)
|
289
|
+
super(hash)
|
290
|
+
rescue Mongo::OperationFailure => e
|
291
|
+
raise e unless e.message =~ /E11000 duplicate key error/
|
292
|
+
nil
|
293
|
+
rescue Mongoid::Errors::Validations => e
|
294
|
+
raise e unless e.document.errors[:provided_id].any?{|s| s =~ /taken/}
|
295
|
+
nil
|
296
|
+
end
|
297
|
+
|
298
|
+
def attrs_to_create(properties)
|
299
|
+
result = super(properties)
|
300
|
+
# 初期登録時、default 値として name には一意な provided_id を name へ登録します
|
301
|
+
result[:name] = result[:provided_id]
|
302
|
+
result
|
303
|
+
end
|
304
|
+
|
305
|
+
def differential_update_by_hash(hash)
|
306
|
+
super(hash) do |virtual_server, properties|
|
307
|
+
virtual_server.save! if virtual_server.changed? && !virtual_server.changes.values.all?{|v| v.nil?}
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
SYNCHRONIZER_CLASSES = {
|
313
|
+
:physical_servers => PhysicalServerSynchronizer,
|
314
|
+
:virtual_server_types => VirtualServerTypeSynchronizer,
|
315
|
+
:virtual_server_images => VirtualServerImageSynchronizer,
|
316
|
+
:virtual_servers => VirtualServerSynchronizer,
|
317
|
+
}.freeze
|
318
|
+
|
319
|
+
end
|
data/tmp/.gitkeep
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,240 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tengine_resource_wakame
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- taigou
|
8
|
+
- totty
|
9
|
+
- g-morita
|
10
|
+
- shyouhei
|
11
|
+
- akm
|
12
|
+
- hiroshinakao
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
date: 2013-04-30 00:00:00.000000000 Z
|
17
|
+
dependencies:
|
18
|
+
- !ruby/object:Gem::Dependency
|
19
|
+
name: tengine_resource
|
20
|
+
requirement: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ~>
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 1.2.0
|
25
|
+
type: :runtime
|
26
|
+
prerelease: false
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ~>
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: 1.2.0
|
32
|
+
- !ruby/object:Gem::Dependency
|
33
|
+
name: wakame-adapters-tengine
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ~>
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: 0.0.0
|
39
|
+
type: :runtime
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.0.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: tengine_resource_ec2
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ~>
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.2.0
|
53
|
+
type: :development
|
54
|
+
prerelease: false
|
55
|
+
version_requirements: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ~>
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 1.2.0
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: bundler
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
- !ruby/object:Gem::Dependency
|
75
|
+
name: rake
|
76
|
+
requirement: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ! '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
type: :development
|
82
|
+
prerelease: false
|
83
|
+
version_requirements: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
- !ruby/object:Gem::Dependency
|
89
|
+
name: rspec
|
90
|
+
requirement: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ~>
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 2.10.0
|
95
|
+
type: :development
|
96
|
+
prerelease: false
|
97
|
+
version_requirements: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 2.10.0
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: yard
|
104
|
+
requirement: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ! '>='
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
type: :development
|
110
|
+
prerelease: false
|
111
|
+
version_requirements: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ! '>='
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
- !ruby/object:Gem::Dependency
|
117
|
+
name: simplecov
|
118
|
+
requirement: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ! '>='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
type: :development
|
124
|
+
prerelease: false
|
125
|
+
version_requirements: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ! '>='
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
- !ruby/object:Gem::Dependency
|
131
|
+
name: autotest
|
132
|
+
requirement: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ! '>='
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
type: :development
|
138
|
+
prerelease: false
|
139
|
+
version_requirements: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ! '>='
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
- !ruby/object:Gem::Dependency
|
145
|
+
name: pry
|
146
|
+
requirement: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - ! '>='
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0'
|
151
|
+
type: :development
|
152
|
+
prerelease: false
|
153
|
+
version_requirements: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
- !ruby/object:Gem::Dependency
|
159
|
+
name: pry-doc
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ! '>='
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
165
|
+
type: :development
|
166
|
+
prerelease: false
|
167
|
+
version_requirements: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - ! '>='
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0'
|
172
|
+
- !ruby/object:Gem::Dependency
|
173
|
+
name: pry-debugger
|
174
|
+
requirement: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - ! '>='
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: '0'
|
179
|
+
type: :development
|
180
|
+
prerelease: false
|
181
|
+
version_requirements: !ruby/object:Gem::Requirement
|
182
|
+
requirements:
|
183
|
+
- - ! '>='
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '0'
|
186
|
+
- !ruby/object:Gem::Dependency
|
187
|
+
name: ZenTest
|
188
|
+
requirement: !ruby/object:Gem::Requirement
|
189
|
+
requirements:
|
190
|
+
- - ~>
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: 4.9.0
|
193
|
+
type: :development
|
194
|
+
prerelease: false
|
195
|
+
version_requirements: !ruby/object:Gem::Requirement
|
196
|
+
requirements:
|
197
|
+
- - ~>
|
198
|
+
- !ruby/object:Gem::Version
|
199
|
+
version: 4.9.0
|
200
|
+
description: tengine_resource_wakame provides physical/virtual server management for
|
201
|
+
wakame-vdc
|
202
|
+
email: tengine-info@groovenauts.jp
|
203
|
+
executables: []
|
204
|
+
extensions: []
|
205
|
+
extra_rdoc_files:
|
206
|
+
- README.rdoc
|
207
|
+
files:
|
208
|
+
- Gemfile
|
209
|
+
- Gemfile.lock
|
210
|
+
- README.rdoc
|
211
|
+
- lib/tengine/resource_wakame/provider.rb
|
212
|
+
- lib/tengine/resource_wakame/provider.rb~
|
213
|
+
- lib/tengine/resource_wakame.rb
|
214
|
+
- lib/tengine_resource_wakame.rb
|
215
|
+
- tmp/.gitkeep
|
216
|
+
homepage: http://github.com/tengine/tengine
|
217
|
+
licenses:
|
218
|
+
- MPL2.0/LGPLv3
|
219
|
+
metadata: {}
|
220
|
+
post_install_message:
|
221
|
+
rdoc_options: []
|
222
|
+
require_paths:
|
223
|
+
- lib
|
224
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
225
|
+
requirements:
|
226
|
+
- - ! '>='
|
227
|
+
- !ruby/object:Gem::Version
|
228
|
+
version: '0'
|
229
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
230
|
+
requirements:
|
231
|
+
- - ! '>='
|
232
|
+
- !ruby/object:Gem::Version
|
233
|
+
version: '0'
|
234
|
+
requirements: []
|
235
|
+
rubyforge_project:
|
236
|
+
rubygems_version: 2.0.3
|
237
|
+
signing_key:
|
238
|
+
specification_version: 4
|
239
|
+
summary: tengine_resource_wakame provides physical/virtual server management for wakame-vdc
|
240
|
+
test_files: []
|