tengine_resource 0.5.15 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. data/Gemfile +1 -27
  2. data/Gemfile.lock +60 -73
  3. data/README.rdoc +2 -2
  4. data/bin/create_indexes_for_tengine_resource +18 -0
  5. data/lib/tengine/resource/config/resource.rb +0 -3
  6. data/lib/tengine/resource/credential.rb +16 -17
  7. data/lib/tengine/resource/net_ssh.rb +22 -10
  8. data/lib/tengine/resource/physical_server.rb +8 -0
  9. data/lib/tengine/resource/provider.rb +206 -35
  10. data/lib/tengine/resource/server.rb +3 -3
  11. data/lib/tengine/resource/virtual_server.rb +1 -1
  12. data/lib/tengine/resource/virtual_server_image.rb +8 -8
  13. data/lib/tengine/resource/virtual_server_type.rb +2 -2
  14. data/lib/tengine/resource/watcher.rb +39 -9
  15. data/tmp/.gitkeep +0 -0
  16. metadata +92 -141
  17. data/.document +0 -5
  18. data/.rspec +0 -1
  19. data/Rakefile +0 -42
  20. data/VERSION +0 -1
  21. data/config/.gitignore +0 -2
  22. data/lib/tengine/resource/credential/ec2.rb +0 -5
  23. data/lib/tengine/resource/credential/ec2/dummy.rb +0 -148
  24. data/lib/tengine/resource/credential/ec2/launch_options.rb +0 -179
  25. data/lib/tengine/resource/provider/ec2.rb +0 -187
  26. data/lib/tengine/resource/provider/wakame.rb +0 -638
  27. data/spec/fixtures/goku_at_ec2_ap_northeast.rb +0 -177
  28. data/spec/mongoid.yml +0 -35
  29. data/spec/mongoid_en.yml +0 -48
  30. data/spec/spec_helper.rb +0 -43
  31. data/spec/support/ec2.rb +0 -129
  32. data/spec/support/mongo_index_key_log.rb +0 -91
  33. data/spec/tengine/resource/bugfix/watcher_for_wakame_spec.rb +0 -232
  34. data/spec/tengine/resource/credential_spec.rb +0 -205
  35. data/spec/tengine/resource/drivers/resource_control_driver_spec.rb +0 -84
  36. data/spec/tengine/resource/net_ssh_spec.rb +0 -148
  37. data/spec/tengine/resource/physical_server_spec.rb +0 -47
  38. data/spec/tengine/resource/provider/ec2_spec.rb +0 -473
  39. data/spec/tengine/resource/provider/test_files/describe_host_nodes.json +0 -22
  40. data/spec/tengine/resource/provider/test_files/describe_images.json +0 -23
  41. data/spec/tengine/resource/provider/test_files/describe_instance_specs.json +0 -23
  42. data/spec/tengine/resource/provider/test_files/describe_instances.json +0 -56
  43. data/spec/tengine/resource/provider/test_files/run_instances.json +0 -30
  44. data/spec/tengine/resource/provider/test_files/terminate_instances.json +0 -3
  45. data/spec/tengine/resource/provider/wakame/00_describe_host_nodes_0_physical_servers.json +0 -8
  46. data/spec/tengine/resource/provider/wakame/01_describe_host_nodes_10_physical_servers.json +0 -139
  47. data/spec/tengine/resource/provider/wakame/02_describe_host_nodes_60_physical_servers.json +0 -795
  48. data/spec/tengine/resource/provider/wakame/10_describe_instances_0_virtual_servers.json +0 -8
  49. data/spec/tengine/resource/provider/wakame/11_describe_instances_10_virtual_servers.json +0 -469
  50. data/spec/tengine/resource/provider/wakame/12_describe_instances_after_run_instances.json +0 -280
  51. data/spec/tengine/resource/provider/wakame/13_describe_instances_after_terminate_instances.json +0 -279
  52. data/spec/tengine/resource/provider/wakame/20_describe_images_0_virtual_server_images.json +0 -8
  53. data/spec/tengine/resource/provider/wakame/21_describe_images_5_virtual_server_images.json +0 -84
  54. data/spec/tengine/resource/provider/wakame/22_describe_images_60_virtual_server_images.json +0 -856
  55. data/spec/tengine/resource/provider/wakame/30_describe_instance_specs_0_virtual_server_specs.json +0 -8
  56. data/spec/tengine/resource/provider/wakame/31_describe_instance_specs_4_virtual_server_specs.json +0 -66
  57. data/spec/tengine/resource/provider/wakame/40_run_instances_0_virtual_servers.json +0 -1
  58. data/spec/tengine/resource/provider/wakame/41_run_instances_1_virtual_servers.json +0 -22
  59. data/spec/tengine/resource/provider/wakame/42_run_instances_5_virtual_servers.json +0 -106
  60. data/spec/tengine/resource/provider/wakame/50_terminate_instances_0_virtual_servers.json +0 -1
  61. data/spec/tengine/resource/provider/wakame/51_terminate_instances_3_virtual_servers.json +0 -5
  62. data/spec/tengine/resource/provider/wakame/sync_physical_servers_spec.rb +0 -114
  63. data/spec/tengine/resource/provider/wakame/sync_virtual_server_images_spec.rb +0 -116
  64. data/spec/tengine/resource/provider/wakame/sync_virtual_server_types_spec.rb +0 -116
  65. data/spec/tengine/resource/provider/wakame/sync_virtual_servers_spec.rb +0 -216
  66. data/spec/tengine/resource/provider/wakame_api_spec.rb +0 -319
  67. data/spec/tengine/resource/provider/wakame_spec.rb +0 -339
  68. data/spec/tengine/resource/provider_spec.rb +0 -252
  69. data/spec/tengine/resource/server_spec.rb +0 -195
  70. data/spec/tengine/resource/test_files/.gitignore +0 -6
  71. data/spec/tengine/resource/test_files/00_describe_host_nodes_0_physical_servers.json +0 -8
  72. data/spec/tengine/resource/test_files/01_describe_host_nodes_10_physical_servers.json +0 -139
  73. data/spec/tengine/resource/test_files/02_describe_host_nodes_60_physical_servers.json +0 -795
  74. data/spec/tengine/resource/test_files/10_describe_instances_0_virtual_servers.json +0 -8
  75. data/spec/tengine/resource/test_files/11_describe_instances_10_virtual_servers.json +0 -469
  76. data/spec/tengine/resource/test_files/12_describe_instances_after_run_instances.json +0 -280
  77. data/spec/tengine/resource/test_files/13_describe_instances_after_terminate_instances.json +0 -279
  78. data/spec/tengine/resource/test_files/14_describe_instances_after_run_1_instance.json +0 -55
  79. data/spec/tengine/resource/test_files/20_describe_images_0_virtual_server_images.json +0 -8
  80. data/spec/tengine/resource/test_files/21_describe_images_5_virtual_server_images.json +0 -84
  81. data/spec/tengine/resource/test_files/22_describe_images_60_virtual_server_images.json +0 -856
  82. data/spec/tengine/resource/test_files/30_describe_instance_specs_0_virtual_server_specs.json +0 -8
  83. data/spec/tengine/resource/test_files/31_describe_instance_specs_4_virtual_server_specs.json +0 -66
  84. data/spec/tengine/resource/test_files/40_run_instances_0_virtual_servers.json +0 -1
  85. data/spec/tengine/resource/test_files/41_run_instances_1_virtual_servers.json +0 -22
  86. data/spec/tengine/resource/test_files/42_run_instances_5_virtual_servers.json +0 -106
  87. data/spec/tengine/resource/test_files/43_run_instances_1_virtual_servers_without_aws_availability_zone.json +0 -22
  88. data/spec/tengine/resource/test_files/50_terminate_instances_0_virtual_servers.json +0 -1
  89. data/spec/tengine/resource/test_files/51_terminate_instances_3_virtual_servers.json +0 -5
  90. data/spec/tengine/resource/virtual_server_image_spec.rb +0 -94
  91. data/spec/tengine/resource/virtual_server_spec.rb +0 -116
  92. data/spec/tengine/resource/virtual_server_type_spec.rb +0 -4
  93. data/spec/tengine/resource/watcher_spec.rb +0 -1027
  94. data/spec/tengine_resource_spec.rb +0 -5
  95. data/tengine_resource.gemspec +0 -172
  96. data/tmp/log/.gitignore +0 -1
data/Gemfile CHANGED
@@ -1,30 +1,4 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  source "http://rubygems.org"
3
3
 
4
- # Add dependencies required to use your gem here.
5
- # Example:
6
- # gem "activesupport", ">= 2.3.5"
7
-
8
- gem "tengine_support", "~> 0.3.27"
9
- gem "tengine_core", "~> 0.5.39"
10
-
11
- gem "wakame-adapters-tengine", "~> 0.0.0"
12
-
13
- # http://rightaws.rubyforge.org/
14
- # http://github.com/rightscale/right_aws
15
- gem "right_aws", "~> 2.1.0"
16
-
17
- gem "net-ssh", "~> 2.2.1"
18
-
19
- # Add dependencies to develop your gem here.
20
- # Include everything needed to run rake, tests, features, etc.
21
- group :development do
22
- gem "rspec", "~> 2.6.0"
23
- gem "factory_girl", "~> 2.1.2"
24
- gem "yard", "~> 0.7.2"
25
- gem "bundler", "~> 1.1.3"
26
- gem "jeweler", "~> 1.6.4"
27
- # gem "rcov", ">= 0"
28
- gem "simplecov", "~> 0.5.3"
29
- gem "ZenTest", "~> 4.6.2"
30
- end
4
+ gemspec
data/Gemfile.lock CHANGED
@@ -1,12 +1,20 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ tengine_resource (1.1.0)
5
+ net-ssh (~> 2.5.2)
6
+ tengine_core (~> 1.1.0)
7
+ tengine_support (~> 1.1.0)
8
+
1
9
  GEM
2
10
  remote: http://rubygems.org/
3
11
  specs:
4
- ZenTest (4.6.2)
5
- activemodel (3.1.4)
6
- activesupport (= 3.1.4)
12
+ ZenTest (4.8.2)
13
+ activemodel (3.2.9)
14
+ activesupport (= 3.2.9)
7
15
  builder (~> 3.0.0)
16
+ activesupport (3.2.9)
8
17
  i18n (~> 0.6)
9
- activesupport (3.1.4)
10
18
  multi_json (~> 1.0)
11
19
  amq-client (0.8.7)
12
20
  amq-protocol (>= 0.8.4)
@@ -16,91 +24,70 @@ GEM
16
24
  amq-client (~> 0.8.7)
17
25
  amq-protocol (~> 0.8.4)
18
26
  eventmachine
19
- bson (1.5.2)
20
- bson_ext (1.5.2)
21
- bson (= 1.5.2)
22
- builder (3.0.0)
23
- daemons (1.1.8)
27
+ autotest (4.4.6)
28
+ ZenTest (>= 4.4.1)
29
+ builder (3.0.4)
30
+ daemons (1.1.9)
24
31
  diff-lcs (1.1.3)
25
- eventmachine (0.12.10)
26
- factory_girl (2.1.2)
27
- activesupport
28
- git (1.2.5)
29
- i18n (0.6.0)
30
- jeweler (1.6.4)
31
- bundler (~> 1.0)
32
- git (>= 1.2.5)
33
- rake
34
- json (1.6.5)
35
- macaddr (1.5.0)
36
- systemu (>= 2.4.0)
37
- mongo (1.5.2)
38
- bson (= 1.5.2)
39
- mongoid (2.3.5)
40
- activemodel (~> 3.1.0)
41
- mongo (~> 1.3)
32
+ eventmachine (1.0.0)
33
+ i18n (0.6.1)
34
+ macaddr (1.6.1)
35
+ systemu (~> 2.5.0)
36
+ mongoid (3.0.15)
37
+ activemodel (~> 3.1)
38
+ moped (~> 1.1)
39
+ origin (~> 1.0)
42
40
  tzinfo (~> 0.3.22)
43
- multi_json (1.0.4)
44
- net-ssh (2.2.2)
41
+ moped (1.3.1)
42
+ multi_json (1.3.6)
43
+ net-ssh (2.5.2)
44
+ origin (1.0.11)
45
45
  rake (0.9.2.2)
46
- right_aws (2.1.0)
47
- right_http_connection (>= 1.2.5)
48
- right_http_connection (1.3.0)
49
- rspec (2.6.0)
50
- rspec-core (~> 2.6.0)
51
- rspec-expectations (~> 2.6.0)
52
- rspec-mocks (~> 2.6.0)
53
- rspec-core (2.6.4)
54
- rspec-expectations (2.6.0)
55
- diff-lcs (~> 1.1.2)
56
- rspec-mocks (2.6.0)
57
- selectable_attr (0.3.15)
46
+ rdiscount (1.6.8)
47
+ rspec (2.10.0)
48
+ rspec-core (~> 2.10.0)
49
+ rspec-expectations (~> 2.10.0)
50
+ rspec-mocks (~> 2.10.0)
51
+ rspec-core (2.10.1)
52
+ rspec-expectations (2.10.0)
53
+ diff-lcs (~> 1.1.3)
54
+ rspec-mocks (2.10.1)
55
+ selectable_attr (0.3.17)
58
56
  i18n
59
- simplecov (0.5.4)
60
- multi_json (~> 1.0.3)
57
+ simplecov (0.6.4)
58
+ multi_json (~> 1.0)
61
59
  simplecov-html (~> 0.5.3)
62
60
  simplecov-html (0.5.3)
63
- systemu (2.5.0)
64
- tengine_core (0.5.39)
65
- activemodel (~> 3.1.0)
66
- activesupport (~> 3.1.0)
67
- bson (~> 1.5.2)
68
- bson_ext (~> 1.5.2)
61
+ systemu (2.5.2)
62
+ tengine_core (1.1.0)
63
+ activemodel (>= 3.1.0)
64
+ activesupport (>= 3.1.0)
69
65
  daemons (~> 1.1.4)
70
- mongo (~> 1.5.2)
71
- mongoid (~> 2.3.3)
66
+ mongoid (~> 3.0.0)
72
67
  selectable_attr (~> 0.3.15)
73
- tengine_event (~> 0.4.9)
74
- tengine_support (~> 0.3.27)
75
- tengine_event (0.4.9)
68
+ tengine_event (~> 1.1.0)
69
+ tengine_support (~> 1.1.0)
70
+ tengine_event (1.1.0)
76
71
  activesupport (>= 3.0.0)
77
72
  amqp (~> 0.8.0)
78
- tengine_support (>= 0.3.27)
73
+ tengine_support (~> 1.1.0)
79
74
  uuid (~> 2.3.4)
80
- tengine_support (0.3.27)
75
+ tengine_support (1.1.0)
81
76
  activesupport (>= 3.0.0)
82
- tzinfo (0.3.33)
77
+ tzinfo (0.3.35)
83
78
  uuid (2.3.5)
84
79
  macaddr (~> 1.0)
85
- wakame-adapters-tengine (0.0.1)
86
- json
87
- right_aws (= 2.1.0)
88
- rspec
89
- yard (0.7.5)
80
+ yard (0.8.2.1)
90
81
 
91
82
  PLATFORMS
92
83
  ruby
93
84
 
94
85
  DEPENDENCIES
95
- ZenTest (~> 4.6.2)
96
- bundler (~> 1.1.3)
97
- factory_girl (~> 2.1.2)
98
- jeweler (~> 1.6.4)
99
- net-ssh (~> 2.2.1)
100
- right_aws (~> 2.1.0)
101
- rspec (~> 2.6.0)
102
- simplecov (~> 0.5.3)
103
- tengine_core (~> 0.5.39)
104
- tengine_support (~> 0.3.27)
105
- wakame-adapters-tengine (~> 0.0.0)
106
- yard (~> 0.7.2)
86
+ autotest
87
+ bundler
88
+ rake (~> 0.9.2.2)
89
+ rdiscount
90
+ rspec (~> 2.10.0)
91
+ simplecov (~> 0.6.4)
92
+ tengine_resource!
93
+ yard (~> 0.8.1)
data/README.rdoc CHANGED
@@ -3,7 +3,7 @@
3
3
  Description goes here.
4
4
 
5
5
  == Contributing to tengine_resource
6
-
6
+
7
7
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
8
  * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
9
  * Fork the project
@@ -13,7 +13,7 @@ Description goes here.
13
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
14
 
15
15
  == License
16
- tengine_event is distributed under the MPL2.0 or LGPLv3 or the dual license of MPL2.0/LGPLv3
16
+ tengine_resource is distributed under the MPL2.0 or LGPLv3 or the dual license of MPL2.0/LGPLv3
17
17
 
18
18
  == Copyright
19
19
 
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ # Use to create indexes. Sample is below.
5
+ # create_indexes_for_tengine_resource localhost:27017/tengine_production
6
+ #
7
+ # Default options
8
+ # hostname localhost
9
+ # port 27017
10
+ # database tengine_production
11
+ #
12
+ require 'tengine_support'
13
+ require 'tengine_resource'
14
+
15
+ include Tengine::Support::Mongoid
16
+
17
+ target = File.expand_path('../lib', File.dirname(__FILE__))
18
+ Tengine::Support::Mongoid.create_indexes(target, ARGV.shift)
@@ -4,13 +4,10 @@ require 'tengine/resource/config'
4
4
 
5
5
  require 'yaml'
6
6
  require 'optparse'
7
- require 'active_support/memoizable'
8
7
 
9
8
  require 'tengine/support/yaml_with_erb'
10
9
 
11
10
  class Tengine::Resource::Config::Resource < Tengine::Support::Config::Definition::Suite
12
- # memoize については http://wota.jp/ac/?date=20081025#p11 などを参照してください
13
- extend ActiveSupport::Memoizable
14
11
 
15
12
  class << self
16
13
  def default_hash
@@ -3,8 +3,6 @@ require 'mongoid'
3
3
  require 'selectable_attr'
4
4
 
5
5
  class Tengine::Resource::Credential
6
- autoload :Ec2, 'tengine/resource/credential/ec2'
7
-
8
6
  include Mongoid::Document
9
7
  include Mongoid::Timestamps
10
8
  include Tengine::Core::SelectableAttr
@@ -24,22 +22,23 @@ class Tengine::Resource::Credential
24
22
  # EC2での認証については以下などを参照してください。
25
23
  # http://builder.japan.zdnet.com/member/u502383/blog/2008/08/08/entry_27012840/
26
24
  selectable_attr :auth_type_cd do
27
- entry "01", :ssh_password , "SSHパスワード認証" , :for_launch => false
28
- entry "02", :ssh_public_key, "SSH公開鍵認証" , :for_launch => false
29
- # entry "03", :ec2_access_key, "EC2 アクセスキー認証", :for_launch => true
25
+ entry "01", :ssh_password , "SSHパスワード認証"
26
+ entry "02", :ssh_public_key, "SSH公開鍵認証"
27
+ # entry "03", :ec2_access_key, "EC2 アクセスキー認証"
30
28
  # entry "04", :ec2_x509_cert, "EC2 X.509認証"
31
- # entry "05", :tama, "Tama", :for_launch => true
29
+ # entry "05", :tama, "Tama"
30
+ entry "06", :ssh_public_key_file, "SSH公開鍵認証(ファイル)"
32
31
  end
33
32
 
34
33
  validates :name, :presence => true, :uniqueness => true, :format => BASE_NAME.options
35
34
  validates :auth_type_cd, :presence => true
36
35
 
37
- index :name, :unique => true
36
+ index({ name: 1 }, { unique: true })
38
37
 
39
- index([ [:_id, Mongo::ASCENDING], [:auth_type_cd, Mongo::ASCENDING], ])
40
- index([ [:_id, Mongo::ASCENDING], [:auth_type_cd, Mongo::DESCENDING], ])
41
- index([ [:_id, Mongo::ASCENDING], [:description, Mongo::ASCENDING], ])
42
- index([ [:_id, Mongo::ASCENDING], [:description, Mongo::DESCENDING], ])
38
+ index _id: 1, auth_type_cd: 1
39
+ index _id: 1, auth_type_cd: -1
40
+ index _id: 1, description: 1
41
+ index _id: 1, description: -1
43
42
 
44
43
  before_validation :prepare_auth_values_default # auth_valuesの各値がnilならデフォルト値を設定します
45
44
  validate{|c| c.validate_auth_values}
@@ -98,11 +97,11 @@ class Tengine::Resource::Credential
98
97
  AuthField.new(:passphrase , :secret, :optional => true),
99
98
  ].freeze,
100
99
 
101
- # {:access_key => "xxxxx", :secret_access_key =>"xxxxx"}
102
- :ec2_access_key => [
103
- AuthField.new(:access_key, :string),
104
- AuthField.new(:secret_access_key, :string),
105
- AuthField.new(:default_region, :string, :default => "us-east-1"),
100
+ # {:username => "goku", :private_key_file =>"xxx", :passphrase => "xxxx"}
101
+ :ssh_public_key_file => [
102
+ AuthField.new(:username , :string),
103
+ AuthField.new(:private_key_file, :string),
104
+ AuthField.new(:passphrase , :secret, :optional => true),
106
105
  ].freeze,
107
106
  }.freeze
108
107
 
@@ -147,7 +146,7 @@ class Tengine::Resource::Credential
147
146
 
148
147
  class << self
149
148
  def find_or_create_by_name!(attrs = {}, &block)
150
- result = self.first(:conditions => {:name => attrs[:name]})
149
+ result = self.where({:name => attrs[:name]}).first
151
150
  result ||= self.create!(attrs)
152
151
  result
153
152
  end
@@ -42,6 +42,8 @@ class << Net::SSH
42
42
  when Hash
43
43
  hash = obj1.symbolize_keys
44
44
  when Tengine::Resource::Credential
45
+ # obj1がCredentialでobj2が指定されていない場合は、objがinvalid?ならエラー
46
+ raise ArgumentError, obj1.errors.full_messages.join if !obj1.valid? && obj2.nil?
45
47
  hash = obj1.auth_values.symbolize_keys
46
48
  else
47
49
  raise TypeError, "#{obj1.class} not expected (expected String)"
@@ -65,6 +67,7 @@ class << Net::SSH
65
67
 
66
68
  u2 = hash.delete(:username)
67
69
  k2 = hash.delete(:private_keys)
70
+ f2 = hash.delete(:private_key_file)
68
71
 
69
72
  raise ArgumentError, "username specified twice in both ordinal and optional arguments" if user and u2
70
73
  user ||= u2
@@ -107,28 +110,37 @@ class << Net::SSH
107
110
 
108
111
  raise ArgumentError, "unknown optional argument(s): #{hash.keys.join(', ')}" unless hash.empty?
109
112
 
110
- if k2
111
- k2 = [k2] unless k2.is_a? Array
113
+ assign_options(argh, k2, f2) do
114
+ return __tengine_resource_net_ssh_backed_up_start__(host, user, argh, &block)
115
+ end
116
+ end
117
+
118
+ def assign_options(options, private_keys, private_key_file)
119
+ if private_keys
120
+ private_keys = [private_keys] unless private_keys.is_a?(Array)
112
121
  Dir.mktmpdir(nil, File.expand_path("../../../../tmp", __FILE__)) do |dir|
113
122
  begin
114
- k3 = k2.map do |k|
123
+ pk_files = private_keys.map do |k|
115
124
  fp = Tempfile.new("pk", dir)
116
125
  fp.write(k)
117
126
  fp.chmod(0400)
118
127
  fp.flush
119
128
  fp # no close
120
129
  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
130
+ options[:keys] ||= []
131
+ options[:keys].concat(pk_files.map {|i| File.expand_path(i.path) })
132
+ yield
126
133
  ensure
127
- k3.each {|i| i.close(:real) }
134
+ pk_files.each {|i| i.close(:real) }
128
135
  end
129
136
  end
137
+ elsif private_key_file
138
+ options[:keys] ||= []
139
+ options[:keys] << private_key_file
140
+ yield
130
141
  else
131
- return __tengine_resource_net_ssh_backed_up_start__ host, user, argh, &block
142
+ yield
132
143
  end
133
144
  end
145
+
134
146
  end
@@ -4,4 +4,12 @@ class Tengine::Resource::PhysicalServer < Tengine::Resource::Server
4
4
 
5
5
  belongs_to :provider, :index => true, :inverse_of => :physical_servers,
6
6
  :class_name => "Tengine::Resource::Provider"
7
+
8
+ class << self
9
+ def by_provided_id(provided_id)
10
+ return nil if provided_id.blank?
11
+ where({:provided_id => provided_id}).first
12
+ end
13
+
14
+ end
7
15
  end
@@ -2,9 +2,6 @@
2
2
  require 'mongoid'
3
3
 
4
4
  class Tengine::Resource::Provider
5
- autoload :Ec2, 'tengine/resource/provider/ec2'
6
- autoload :Wakame, 'tengine/resource/provider/wakame'
7
-
8
5
  include Mongoid::Document
9
6
  include Mongoid::Timestamps
10
7
  include Tengine::Core::Validation
@@ -18,7 +15,7 @@ class Tengine::Resource::Provider
18
15
  field :properties, :type => Hash, :default => {}
19
16
 
20
17
  validates :name, :presence => true, :uniqueness => true, :format => BASE_NAME.options
21
- index :name, :unique => true
18
+ index({ name: 1 }, { unique: true })
22
19
 
23
20
  with_options(:inverse_of => :provider, :dependent => :destroy) do |c|
24
21
  c.has_many :physical_servers , :class_name => "Tengine::Resource::PhysicalServer"
@@ -28,55 +25,229 @@ class Tengine::Resource::Provider
28
25
  end
29
26
 
30
27
  # 仮想サーバタイプの監視
31
- def virtual_server_type_watch ; raise NotImplementedError end
28
+ def synchronize_virtual_server_types ; raise NotImplementedError end
32
29
  # 物理サーバの監視
33
- def physical_server_watch ; raise NotImplementedError end
30
+ def synchronize_physical_servers ; raise NotImplementedError end
34
31
  # 仮想サーバの監視
35
- def virtual_server_watch ; raise NotImplementedError end
32
+ def synchronize_virtual_servers ; raise NotImplementedError end
36
33
  # 仮想サーバイメージの監視
37
- def virtual_server_image_watch ; raise NotImplementedError end
34
+ def synchronize_virtual_server_images ; raise NotImplementedError end
38
35
 
39
36
  def update_physical_servers ; raise NotImplementedError end
40
37
  def update_virtual_servers ; raise NotImplementedError end
41
38
  def update_virtual_server_imagess; raise NotImplementedError end
42
39
 
40
+
41
+ def find_virtual_server_on_duplicaion_error(virtual_server_provided_id)
42
+ begin
43
+ yield
44
+ rescue Moped::Errors::OperationFailure => e
45
+ raise e unless e.message =~ /E11000 duplicate key error/
46
+ self.virtual_servers.where({:provided_id => virtual_server_provided_id}).first or
47
+ raise "VirtualServer not found for #{virtual_server_provided_id}"
48
+ rescue Mongoid::Errors::Validations => e
49
+ raise e unless e.document.errors[:provided_id].any?{|s| s =~ /taken/}
50
+ self.virtual_servers.where({:provided_id => virtual_server_provided_id}).first or
51
+ raise "VirtualServer not found for #{virtual_server_provided_id}"
52
+ end
53
+ end
54
+
55
+ class << self
56
+ def find_or_create_by_name!(attrs)
57
+ result = self.where({:name => attrs[:name]}).first
58
+ result ||= self.create!(attrs)
59
+ result
60
+ end
61
+
62
+ def synchronizers
63
+ @synchronizers ||= {}
64
+ end
65
+
66
+ def register_synchronizers(hash)
67
+ synchronizers.update(hash)
68
+ end
69
+ end
70
+
43
71
  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])
72
+
73
+ def synchronize_by(target_name)
74
+ synchronizer = synchronizers_by(target_name)
75
+ synchronizer.execute
76
+ end
77
+
78
+ def synchronizers_by(target_name)
79
+ unless @synchronizers
80
+ @synchronizers = {}
81
+ self.class.synchronizers.each do |target_name, klass|
82
+ @synchronizers[target_name] = klass.new(self, target_name)
55
83
  end
56
- found_ids << server.id
57
84
  end
58
- self.physical_servers.not_in(:_id => found_ids).update_all(:status => "not_found")
85
+ @synchronizers[target_name]
59
86
  end
60
87
 
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)
88
+ public
89
+
90
+ class Synchronizer
91
+ class << self
92
+ def fetch_known_target_method(method_name = nil)
93
+ @fetch_known_target_methods ||= {}
94
+ @fetch_known_target_methods[self] = method_name if method_name
95
+ @fetch_known_target_methods[self]
96
+ end
97
+
98
+ def map(attr_name, prop_name = nil, &block)
99
+ property_map[attr_name] = prop_name || block
100
+ end
101
+
102
+ def property_map
103
+ @property_map ||= {}
104
+ @property_map[self] ||= {}
105
+ end
106
+ end
107
+
108
+ def fetch_known_target_method
109
+ self.class.fetch_known_target_method
110
+ end
111
+
112
+ def property_map
113
+ @property_map ||= self.class.property_map
114
+ end
115
+
116
+ attr_reader :provider, :target_name, :log_prefix
117
+ def initialize(provider, target_name)
118
+ @provider, @target_name = provider, target_name
119
+ @log_prefix = "#{self.class.name} for #{provider.name}"
120
+ end
121
+
122
+ def execute
123
+ actual_target_hashs = fetch_actual_target_hashs
124
+
125
+ provider.reload
126
+ known_targets = fetch_known_targets
127
+
128
+ id_key = property_map[:provided_id].to_s
129
+ updated_target_hashs = []
130
+ destroyed_targets = []
131
+
132
+ known_targets.each do |known_target|
133
+ actual_target_hash = actual_target_hashs.detect do |t|
134
+ (t[id_key] || t[id_key.to_sym]) == known_target.provided_id
135
+ end
136
+ if actual_target_hash
137
+ updated_target_hashs << actual_target_hash
138
+ else
139
+ destroyed_targets << known_target
140
+ end
141
+ end
142
+ created_target_hashs = actual_target_hashs - updated_target_hashs
143
+
144
+ differential_update(updated_target_hashs)
145
+ create_by_hashs(created_target_hashs)
146
+ destroy_targets(destroyed_targets)
147
+ end
148
+
149
+ private
150
+
151
+ # APIからの実際のターゲット情報を取得する
152
+ def fetch_actual_target_hashs
153
+ Tengine.logger.debug "#{log_prefix} #{fetch_known_target_method} for api (wakame)"
154
+ result = provider.send(fetch_known_target_method)
155
+ Tengine.logger.debug "#{log_prefix} #{result.inspect}"
156
+ result
157
+ end
158
+
159
+ # DBに記録されているターゲット情報を取得する
160
+ def fetch_known_targets
161
+ Tengine.logger.debug "#{log_prefix} #{target_name} on provider (#{provider.name})"
162
+ result = provider.send(target_name)
163
+ Tengine.logger.debug "#{log_prefix} #{result.inspect}"
164
+ result
165
+ end
166
+
167
+
168
+ def differential_update(hashs)
169
+ hashs.map{|hash| differential_update_by_hash(hash)}
170
+ end
171
+
172
+ def differential_update_by_hash(hash, &block)
173
+ properties = hash.dup
174
+ properties.deep_symbolize_keys!
175
+ provided_id = properties[ property_map[:provided_id] ]
176
+ Tengine.logger.debug "#{log_prefix} update (#{provided_id})"
177
+ target = provider.send(target_name).where(:provided_id => provided_id).first
178
+ unless target
179
+ raise "target #{target_name.to_s.singularize} not found by using #{map[:provided_id]}: #{provided_id.inspect}. properties: #{properties.inspect}"
180
+ end
181
+ attrs = mapped_attributes(properties)
182
+ attrs.each do |attr, value|
183
+ target.send("#{attr}=", value)
184
+ end
185
+ prop_backup = properties.dup
186
+ if target.respond_to?(:properties) && target.properties
187
+ properties.each do |key, val|
188
+ value = properties.delete(key)
189
+ if (val.to_s != value.to_s) or (value.blank?)
190
+ if target.properties[key.to_sym]
191
+ target.properties[key.to_sym] = value
192
+ else
193
+ target.properties[key.to_s] = value
194
+ end
195
+ end
196
+ end
197
+ end
198
+ if block
199
+ block.call(target, prop_backup)
67
200
  else
68
- server = self.virtual_servers.create!(hash.merge(:name => hash[:provided_id]))
201
+ target.save! if target.changed?
69
202
  end
70
- found_ids << server.id
203
+ rescue => e
204
+ Tengine.logger.error "#{log_prefix} [#{e.class}] #{e.message}: failed to update (#{provided_id}): #{hash.inspect}"
205
+ raise
71
206
  end
72
- self.virtual_servers.not_in(:_id => found_ids).destroy_all
73
- end
74
207
 
75
- class << self
76
- def find_or_create_by_name!(attrs)
77
- result = self.first(:conditions => {:name => attrs[:name]})
78
- result ||= self.create!(attrs)
208
+ def create_by_hashs(hashs)
209
+ hashs.map{|hash| t = create_by_hash(hash); t ? t.id : nil}.compact
210
+ end
211
+
212
+ def create_by_hash(hash)
213
+ properties = hash.dup
214
+ properties.deep_symbolize_keys!
215
+ provided_id = properties[:provided_id]
216
+ Tengine.logger.debug "#{log_prefix} create #{provided_id}"
217
+ attrs = attrs_to_create(properties)
218
+ target = provider.send(target_name).new
219
+ attrs[:properties] = properties if target.respond_to?(:properties)
220
+ yield(attrs) if block_given?
221
+ target.attributes = attrs
222
+ target.save!
223
+ target
224
+ rescue => e
225
+ Tengine.logger.error "#{log_prefix} [#{e.class}] #{e.message}: failed to create (#{provided_id}): #{hash.inspect}"
226
+ raise
227
+ end
228
+
229
+ def attrs_to_create(properties)
230
+ mapped_attributes(properties)
231
+ end
232
+
233
+ def mapped_attributes(properties)
234
+ result = {}
235
+ property_map.each do |attr, prop|
236
+ value = prop.is_a?(Proc) ?
237
+ prop.call(properties, provider) : # 引数を一つだけ使うこともあるのlambdaではなくProc.newを使う事を期待しています。
238
+ properties.delete(prop)
239
+ result[attr] = value
240
+ end
79
241
  result
80
242
  end
243
+
244
+ def destroy_targets(targets)
245
+ targets.each do |target|
246
+ Tengine.logger.debug "#{log_prefix} destroy #{target.provided_id}"
247
+ target.destroy
248
+ end
249
+ end
250
+
81
251
  end
252
+
82
253
  end