corl 0.4.1 → 0.4.2

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.
Files changed (48) hide show
  1. data/.gitmodules +1 -1
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +15 -8
  4. data/VERSION +1 -1
  5. data/bootstrap/os/ubuntu/00_base.sh +10 -1
  6. data/bootstrap/os/ubuntu/05_ruby.sh +6 -0
  7. data/bootstrap/os/ubuntu/06_puppet.sh +6 -6
  8. data/bootstrap/os/ubuntu/09_nucleon.sh +14 -0
  9. data/bootstrap/os/ubuntu/10_corl.sh +7 -2
  10. data/corl.gemspec +16 -9
  11. data/lib/CORL/action/authorize.rb +57 -0
  12. data/lib/CORL/action/bootstrap.rb +5 -0
  13. data/lib/CORL/action/destroy.rb +64 -0
  14. data/lib/CORL/action/exec.rb +9 -0
  15. data/lib/CORL/action/image.rb +39 -7
  16. data/lib/CORL/action/images.rb +4 -3
  17. data/lib/CORL/action/lookup.rb +2 -2
  18. data/lib/CORL/action/regions.rb +51 -0
  19. data/lib/CORL/action/seed.rb +1 -1
  20. data/lib/CORL/action/spawn.rb +8 -9
  21. data/lib/CORL/action/ssh.rb +74 -0
  22. data/lib/CORL/action/start.rb +37 -5
  23. data/lib/CORL/action/stop.rb +37 -5
  24. data/lib/CORL/configuration/file.rb +34 -7
  25. data/lib/CORL/event/puppet.rb +1 -1
  26. data/lib/CORL/machine/aws.rb +153 -0
  27. data/lib/CORL/machine/physical.rb +14 -5
  28. data/lib/CORL/machine/rackspace.rb +58 -0
  29. data/lib/CORL/network/default.rb +1 -1
  30. data/lib/CORL/node/aws.rb +40 -16
  31. data/lib/CORL/node/local.rb +4 -3
  32. data/lib/CORL/node/rackspace.rb +25 -7
  33. data/lib/CORL/provisioner/puppetnode.rb +11 -9
  34. data/lib/core/errors.rb +6 -0
  35. data/lib/core/mod/fog_aws_server.rb +38 -0
  36. data/lib/core/plugin/action.rb +3 -11
  37. data/lib/core/plugin/configuration.rb +20 -2
  38. data/lib/{CORL/machine/fog.rb → core/plugin/fog_machine.rb} +92 -92
  39. data/lib/core/plugin/{fog.rb → fog_node.rb} +20 -7
  40. data/lib/core/plugin/machine.rb +58 -37
  41. data/lib/core/plugin/network.rb +76 -111
  42. data/lib/core/plugin/node.rb +271 -87
  43. data/lib/core/plugin/provisioner.rb +1 -1
  44. data/lib/corl.rb +6 -14
  45. data/locales/en.yml +18 -1
  46. metadata +39 -32
  47. data/lib/CORL/node/google.rb +0 -111
  48. data/lib/core/util/ssh.rb +0 -286
@@ -1,10 +1,16 @@
1
1
 
2
2
  module CORL
3
3
  module Node
4
- class Rackspace < Node::Fog
4
+ class Rackspace < Fog
5
5
 
6
6
  #-----------------------------------------------------------------------------
7
7
  # Node plugin interface
8
+
9
+ def normalize(reload)
10
+ super do
11
+ :rackspace
12
+ end
13
+ end
8
14
 
9
15
  #-----------------------------------------------------------------------------
10
16
  # Checks
@@ -41,21 +47,33 @@ class Rackspace < Node::Fog
41
47
  end
42
48
  end
43
49
 
50
+ #---
51
+
52
+ def create_config
53
+ { :name => hostname, :flavor_id => machine_type, :image_id => image }
54
+ end
55
+
44
56
  #-----------------------------------------------------------------------------
45
57
  # Node operations
46
58
 
47
59
  def create(options = {})
48
60
  super do |op, config|
49
61
  if op == :config
50
- config.defaults({
51
- :name => hostname,
52
- :flavor_id => machine_type,
53
- :image_id => image
54
- })
62
+ config.defaults(create_config)
55
63
  end
56
64
  end
57
65
  end
58
-
66
+
67
+ #---
68
+
69
+ def start(options = {})
70
+ super do |op, config|
71
+ if op == :config
72
+ config.defaults(create_config)
73
+ end
74
+ end
75
+ end
76
+
59
77
  #-----------------------------------------------------------------------------
60
78
  # Utilities
61
79
 
@@ -6,20 +6,22 @@ class Puppetnode < CORL.plugin_class(:provisioner)
6
6
  #-----------------------------------------------------------------------------
7
7
  # Provisioner plugin interface
8
8
 
9
- def normalize
9
+ def normalize(reload)
10
10
  super
11
11
 
12
- require 'puppet'
12
+ unless reload
13
+ require 'puppet'
13
14
 
14
- if CORL.log_level == :debug
15
- Puppet.debug = true
16
- end
17
- Puppet.initialize_settings
15
+ if CORL.log_level == :debug
16
+ Puppet.debug = true
17
+ end
18
+ Puppet.initialize_settings
18
19
 
19
- myself.plugin_name = :default if plugin_name.to_sym == :puppetnode
20
+ myself.plugin_name = :default if plugin_name.to_sym == :puppetnode
20
21
 
21
- @env = Puppet::Node::Environment.new
22
- @compiler = Puppet::Parser::Compiler.new(node)
22
+ @env = Puppet::Node::Environment.new
23
+ @compiler = Puppet::Parser::Compiler.new(node)
24
+ end
23
25
 
24
26
  init_scope
25
27
  register
@@ -0,0 +1,6 @@
1
+
2
+ module CORL
3
+ module Errors
4
+
5
+ end
6
+ end
@@ -0,0 +1,38 @@
1
+ module Fog
2
+ module Compute
3
+ class AWS
4
+ class Server
5
+
6
+ def setup(credentials = {})
7
+ requires :ssh_ip_address, :username
8
+
9
+ commands = [
10
+ %{mkdir .ssh},
11
+ %{passwd -l #{username}},
12
+ %{echo "#{Fog::JSON.encode(Fog::JSON.sanitize(attributes))}" >> ~/attributes.json}
13
+ ]
14
+ if public_key
15
+ commands << %{echo "#{public_key}" >> ~/.ssh/authorized_keys}
16
+ end
17
+
18
+ tries = 5
19
+ sleep_secs = 5
20
+
21
+ begin
22
+ Nucleon::Util::SSH.session(ssh_ip_address, username, ssh_port, private_key_path, true)
23
+ results = Nucleon::Util::SSH.exec(ssh_ip_address, username, commands)
24
+
25
+ rescue Exception => error
26
+ if tries > 1
27
+ sleep(sleep_secs)
28
+ tries -= 1
29
+ retry
30
+ else
31
+ raise error
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -26,6 +26,7 @@ class CloudAction < CORL.plugin_class(:action)
26
26
  node_plugins = CORL.loaded_plugins(:node)
27
27
 
28
28
  register :parallel, :bool, true, 'corl.core.action.options.parallel'
29
+ register :net_remote, :str, :edit, 'corl.core.action.options.net_remote'
29
30
  register :net_provider, :str, :default, 'corl.core.action.options.net_provider' do |value|
30
31
  value = value.to_sym
31
32
  network_plugins = CORL.loaded_plugins(:network)
@@ -62,7 +63,7 @@ class CloudAction < CORL.plugin_class(:action)
62
63
  #---
63
64
 
64
65
  def node_ignore
65
- [ :parallel, :net_provider, :node_provider, :nodes ]
66
+ [ :parallel, :net_remote, :net_provider, :node_provider, :nodes ]
66
67
  end
67
68
 
68
69
  #-----------------------------------------------------------------------------
@@ -102,16 +103,7 @@ class CloudAction < CORL.plugin_class(:action)
102
103
  exec_config.delete(:node_provider)
103
104
 
104
105
  result = node.action(plugin_provider, exec_config) do |op, data|
105
- ui_group(node.plugin_name) do
106
- case op
107
- when :config # Modify seed execution configurations
108
- render("Starting remote execution of #{plugin_provider} action")
109
- when :process # Process final result
110
- render("Successfully finished remote execution of #{plugin_provider} action")
111
- end
112
- data = execute_remote(node, network, op, data)
113
- end
114
- data
106
+ execute_remote(node, network, op, data)
115
107
  end
116
108
  result.status == code.success
117
109
  end
@@ -8,11 +8,11 @@ class Configuration < CORL.plugin_class(:base)
8
8
  #-----------------------------------------------------------------------------
9
9
  # Configuration plugin interface
10
10
 
11
- def normalize
11
+ def normalize(reload)
12
12
  super
13
13
 
14
14
  logger.debug("Initializing source sub configuration")
15
- init_subconfig(true)
15
+ init_subconfig(true) unless reload
16
16
 
17
17
  _init(:autoload, true)
18
18
  _init(:autosave, false)
@@ -172,6 +172,24 @@ class Configuration < CORL.plugin_class(:base)
172
172
  end
173
173
  new_location
174
174
  end
175
+
176
+ #---
177
+
178
+ def delete_attachments(type, ids, options = {})
179
+ method_config = Config.ensure(options)
180
+ locations = []
181
+
182
+ if can_persist?
183
+ if extension_check(:remove_attachments, { :config => method_config })
184
+ logger.info("Removing attached data from source configuration")
185
+
186
+ locations = yield(method_config) if block_given?
187
+ end
188
+ else
189
+ logger.warn("Can not remove attached data from source configuration")
190
+ end
191
+ locations
192
+ end
175
193
  end
176
194
  end
177
195
  end
@@ -1,4 +1,8 @@
1
1
 
2
+ nucleon_require(File.dirname(__FILE__), :machine)
3
+
4
+ #---
5
+
2
6
  module CORL
3
7
  module Machine
4
8
  class Fog < CORL.plugin_class(:machine)
@@ -25,8 +29,8 @@ class Fog < CORL.plugin_class(:machine)
25
29
 
26
30
  ENV['DEBUG'] = 'true' if CORL.log_level == :debug
27
31
 
28
- require 'fog'
29
-
32
+ require 'fog'
33
+
30
34
  myself.compute = ::Fog::Compute.new(export)
31
35
  end
32
36
  protected :set_connection
@@ -45,28 +49,14 @@ class Fog < CORL.plugin_class(:machine)
45
49
  #---
46
50
 
47
51
  def server=id
52
+ @server = nil
53
+
48
54
  if id.is_a?(String)
49
- @server = compute.servers.get(id)
50
- else
55
+ @server = compute.servers.get(id) unless id.empty?
56
+ elsif ! id.nil?
51
57
  @server = id
52
- end
53
-
54
- unless @server.nil?
55
- myself.name = @server.id
56
-
57
- node[:id] = plugin_name
58
- node[:hostname] = @server.name
59
- node[:public_ip] = @server.public_ip_address
60
- node[:private_ip] = @server.private_ip_address
61
-
62
- node.machine_type = @server.flavor.id
63
- node.image = @server.image.id
64
-
65
- node.user = @server.username unless node.user
66
-
67
- @server.private_key_path = node.private_key if node.private_key
68
- @server.public_key_path = node.public_key if node.public_key
69
- end
58
+ end
59
+ init_server
70
60
  end
71
61
 
72
62
  def server
@@ -81,14 +71,7 @@ class Fog < CORL.plugin_class(:machine)
81
71
  return translate_state(server.state) if server
82
72
  nil
83
73
  end
84
-
85
- #---
86
-
87
- def hostname
88
- return server.name if server
89
- nil
90
- end
91
-
74
+
92
75
  #---
93
76
 
94
77
  def public_ip
@@ -134,18 +117,30 @@ class Fog < CORL.plugin_class(:machine)
134
117
  #-----------------------------------------------------------------------------
135
118
  # Management
136
119
 
120
+ def init_server
121
+ unless @server.nil?
122
+ yield # Implement in fog machine providers
123
+ end
124
+ end
125
+ protected :init_server
126
+
127
+ #---
128
+
137
129
  def load
138
130
  super do
139
- myself.server = plugin_name if compute && ! plugin_name.empty?
140
- server.nil? ? false : true
131
+ myself.server = plugin_name if compute && plugin_name
132
+ ! plugin_name && @server.nil? ? false : true
141
133
  end
142
134
  end
143
135
 
144
136
  #---
145
137
 
146
138
  def create(options = {})
147
- super do
148
- myself.server = compute.servers.bootstrap(Config.ensure(options).export) if compute
139
+ super do |config|
140
+ if compute
141
+ yield(config) if block_given?
142
+ myself.server = compute.servers.bootstrap(config.export)
143
+ end
149
144
  myself.server ? true : false
150
145
  end
151
146
  end
@@ -157,7 +152,7 @@ class Fog < CORL.plugin_class(:machine)
157
152
  logger.debug("Executing SCP download to #{local_path} from #{remote_path} on machine #{name}")
158
153
 
159
154
  begin
160
- if init_ssh_session
155
+ if init_ssh_session(server)
161
156
  Util::SSH.download(node.public_ip, node.user, remote_path, local_path, config.export) do |name, received, total|
162
157
  yield(name, received, total) if block_given?
163
158
  end
@@ -176,10 +171,10 @@ class Fog < CORL.plugin_class(:machine)
176
171
 
177
172
  def upload(local_path, remote_path, options = {})
178
173
  super do |config, success|
179
- logger.debug("Executing SCP upload from #{local_path} to #{remote_path} on machine #{name}")
174
+ logger.debug("Executing SCP upload from #{local_path} to #{remote_path} on machine #{plugin_name}")
180
175
 
181
176
  begin
182
- if init_ssh_session
177
+ if init_ssh_session(server)
183
178
  Util::SSH.upload(node.public_ip, node.user, local_path, remote_path, config.export) do |name, sent, total|
184
179
  yield(name, sent, total) if block_given?
185
180
  end
@@ -199,9 +194,9 @@ class Fog < CORL.plugin_class(:machine)
199
194
  def exec(commands, options = {})
200
195
  super do |config, results|
201
196
  if commands
202
- logger.debug("Executing SSH commands ( #{commands.inspect} ) on machine #{name}")
197
+ logger.debug("Executing SSH commands ( #{commands.inspect} ) on machine #{plugin_name}")
203
198
 
204
- if init_ssh_session
199
+ if init_ssh_session(server)
205
200
  results = Util::SSH.exec(node.public_ip, node.user, commands) do |type, command, data|
206
201
  yield(type, command, data) if block_given?
207
202
  end
@@ -215,72 +210,51 @@ class Fog < CORL.plugin_class(:machine)
215
210
 
216
211
  #---
217
212
 
218
- def start(options = {})
219
- super do
220
- if compute
221
- server_info = compute.servers.create(options)
222
-
223
- logger.info("Waiting for #{plugin_provider} machine to start")
224
- ::Fog.wait_for do
225
- compute.servers.get(server_info.id).ready? ? true : false
226
- end
227
-
228
- logger.debug("Setting machine #{server_info.id}")
229
-
230
- myself.server = compute.servers.get(server_info.id)
231
- myself.server ? true : false
232
- else
233
- false
234
- end
213
+ def terminal(user, options = {})
214
+ super do |config|
215
+ Util::SSH.terminal(node.public_ip, user, config.export)
235
216
  end
236
217
  end
237
218
 
238
219
  #---
239
220
 
240
221
  def reload(options = {})
241
- super do
222
+ super do |config|
223
+ success = false
242
224
  if server
243
- logger.debug("Rebooting machine #{name}")
244
- server.reboot(options)
245
- else
246
- false
247
- end
225
+ success = block_given? ? yield(config) : true
226
+ success = init_ssh_session(server, true, config.get(:tries, 5), config.get(:sleep_time, 5)) if success
227
+ end
228
+ success
248
229
  end
249
230
  end
250
231
 
251
232
  #---
252
233
 
253
- def create_image(name, options = {})
254
- super do
234
+ def create_image(options = {})
235
+ super do |config|
236
+ success = false
255
237
  if server
256
- logger.debug("Imaging machine #{self.name}")
257
- image = server.create_image(name, options)
258
-
259
- if image
260
- node.image = image.id
261
- true
262
- else
263
- false
264
- end
265
- else
266
- false
238
+ logger.debug("Imaging machine #{plugin_name}")
239
+
240
+ image_name = sprintf("%s (%s)", node.plugin_name, Time.now.to_s)
241
+ success = yield(image_name, config, success) if block_given? # Implement in sub classes
242
+ success = init_ssh_session(server, true, config.get(:tries, 5), config.get(:sleep_time, 5)) if success
267
243
  end
244
+ success
268
245
  end
269
246
  end
270
247
 
271
248
  #---
272
249
 
273
250
  def stop(options = {})
274
- super do
251
+ super do |config|
275
252
  success = true
276
- if image_id = create_image(name)
277
- logger.info("Waiting for #{plugin_provider} machine to finish creating image: #{image_id}")
278
- ::Fog.wait_for do
279
- compute.images.get(image_id).ready? ? true : false
280
- end
281
-
282
- logger.debug("Detroying machine #{name}")
283
- success = server.destroy
253
+ if server && create_image(config)
254
+ logger.debug("Stopping machine #{plugin_name}")
255
+ success = destroy(config.import({ :stop => true }))
256
+ else
257
+ success = false
284
258
  end
285
259
  success
286
260
  end
@@ -289,21 +263,47 @@ class Fog < CORL.plugin_class(:machine)
289
263
  #---
290
264
 
291
265
  def destroy(options = {})
292
- super do
266
+ super do |config|
267
+ success = false
293
268
  if server
294
- logger.debug("Destroying machine #{name}")
295
- server.destroy(options)
296
- else
297
- false
298
- end
269
+ logger.debug("Destroying machine #{plugin_name}")
270
+ success = server.destroy
271
+ success = yield(config) if success && block_given?
272
+ end
273
+ close_ssh_session if success
274
+ success
299
275
  end
300
276
  end
301
277
 
302
278
  #-----------------------------------------------------------------------------
303
279
  # Utilities
304
280
 
305
- def init_ssh_session
306
- Util::SSH.session(node.public_ip, node.user, node.ssh_port, node.private_key)
281
+ def init_ssh_session(server, reset = false, tries = 5, sleep_secs = 5)
282
+ server.wait_for { ready? }
283
+
284
+ success = true
285
+
286
+ begin
287
+ Util::SSH.session(node.public_ip, node.user, node.ssh_port, node.private_key, reset)
288
+
289
+ rescue Exception => error
290
+ if tries > 1
291
+ sleep(sleep_secs)
292
+
293
+ tries -= 1
294
+ reset = true
295
+ retry
296
+ else
297
+ success = false
298
+ end
299
+ end
300
+ success
301
+ end
302
+
303
+ #---
304
+
305
+ def close_ssh_session
306
+ Util::SSH.close_session(node.public_ip, node.user)
307
307
  end
308
308
  end
309
309
  end
@@ -10,12 +10,17 @@ class Fog < CORL.plugin_class(:node)
10
10
  #-----------------------------------------------------------------------------
11
11
  # Node plugin interface
12
12
 
13
- def normalize
14
- super
15
- myself.region = region
16
-
17
- yield if block_given?
18
- myself.machine = create_machine(:machine, :fog, machine_config)
13
+ def normalize(reload)
14
+ super do
15
+ myself.region = region
16
+
17
+ unless reload
18
+ machine_provider = :fog
19
+ machine_provider = yield if block_given?
20
+
21
+ myself.machine = create_machine(:machine, machine_provider, machine_config)
22
+ end
23
+ end
19
24
  end
20
25
 
21
26
  #-----------------------------------------------------------------------------
@@ -94,6 +99,12 @@ class Fog < CORL.plugin_class(:node)
94
99
 
95
100
  #---
96
101
 
102
+ def key_config
103
+ { :private_key_path => private_key, :public_key_path => public_key }
104
+ end
105
+
106
+ #---
107
+
97
108
  def exec_options(name, options = {})
98
109
  extended_config(name, options).export
99
110
  end
@@ -105,8 +116,9 @@ class Fog < CORL.plugin_class(:node)
105
116
  super do |op, config|
106
117
  if op == :config
107
118
  config.import(exec_options(:create))
119
+ config.defaults(key_config)
108
120
  end
109
- yield(op, config) if block_given?
121
+ yield(op, config) if block_given?
110
122
  end
111
123
  end
112
124
 
@@ -149,6 +161,7 @@ class Fog < CORL.plugin_class(:node)
149
161
  super do |op, config|
150
162
  if op == :config
151
163
  config.import(exec_options(:start))
164
+ config.defaults(key_config)
152
165
  end
153
166
  yield(op, config) if block_given?
154
167
  end