corl 0.4.0

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 (132) hide show
  1. data/.document +5 -0
  2. data/.gitmodules +4 -0
  3. data/Gemfile +24 -0
  4. data/Gemfile.lock +123 -0
  5. data/LICENSE.txt +674 -0
  6. data/README.rdoc +27 -0
  7. data/Rakefile +78 -0
  8. data/VERSION +1 -0
  9. data/bin/corl +55 -0
  10. data/corl.gemspec +228 -0
  11. data/lib/corl/action/add.rb +69 -0
  12. data/lib/corl/action/bootstrap.rb +83 -0
  13. data/lib/corl/action/clone.rb +40 -0
  14. data/lib/corl/action/create.rb +55 -0
  15. data/lib/corl/action/exec.rb +41 -0
  16. data/lib/corl/action/extract.rb +49 -0
  17. data/lib/corl/action/image.rb +30 -0
  18. data/lib/corl/action/images.rb +55 -0
  19. data/lib/corl/action/lookup.rb +35 -0
  20. data/lib/corl/action/machines.rb +51 -0
  21. data/lib/corl/action/provision.rb +37 -0
  22. data/lib/corl/action/remove.rb +51 -0
  23. data/lib/corl/action/save.rb +53 -0
  24. data/lib/corl/action/seed.rb +115 -0
  25. data/lib/corl/action/spawn.rb +75 -0
  26. data/lib/corl/action/start.rb +37 -0
  27. data/lib/corl/action/stop.rb +30 -0
  28. data/lib/corl/action/update.rb +37 -0
  29. data/lib/corl/command/shell.rb +164 -0
  30. data/lib/corl/configuration/file.rb +386 -0
  31. data/lib/corl/event/puppet.rb +90 -0
  32. data/lib/corl/event/regex.rb +52 -0
  33. data/lib/corl/extension/puppetloader.rb +24 -0
  34. data/lib/corl/machine/fog.rb +310 -0
  35. data/lib/corl/machine/physical.rb +161 -0
  36. data/lib/corl/network/default.rb +26 -0
  37. data/lib/corl/node/aws.rb +90 -0
  38. data/lib/corl/node/fog.rb +198 -0
  39. data/lib/corl/node/google.rb +115 -0
  40. data/lib/corl/node/local.rb +26 -0
  41. data/lib/corl/node/rackspace.rb +89 -0
  42. data/lib/corl/project/git.rb +465 -0
  43. data/lib/corl/project/github.rb +108 -0
  44. data/lib/corl/provisioner/puppetnode/resource.rb +245 -0
  45. data/lib/corl/provisioner/puppetnode/resource_group.rb +205 -0
  46. data/lib/corl/provisioner/puppetnode.rb +407 -0
  47. data/lib/corl/template/environment.rb +73 -0
  48. data/lib/corl/template/json.rb +16 -0
  49. data/lib/corl/template/wrapper.rb +16 -0
  50. data/lib/corl/template/yaml.rb +16 -0
  51. data/lib/corl/translator/json.rb +27 -0
  52. data/lib/corl/translator/yaml.rb +27 -0
  53. data/lib/corl.rb +173 -0
  54. data/lib/corl_core/codes.rb +107 -0
  55. data/lib/corl_core/config/collection.rb +57 -0
  56. data/lib/corl_core/config/options.rb +70 -0
  57. data/lib/corl_core/config.rb +337 -0
  58. data/lib/corl_core/core.rb +59 -0
  59. data/lib/corl_core/corl.rb +254 -0
  60. data/lib/corl_core/errors.rb +84 -0
  61. data/lib/corl_core/facade.rb +126 -0
  62. data/lib/corl_core/gems.rb +72 -0
  63. data/lib/corl_core/manager.rb +425 -0
  64. data/lib/corl_core/mixin/action/commit.rb +58 -0
  65. data/lib/corl_core/mixin/action/keypair.rb +105 -0
  66. data/lib/corl_core/mixin/action/node.rb +129 -0
  67. data/lib/corl_core/mixin/action/project.rb +53 -0
  68. data/lib/corl_core/mixin/action/push.rb +52 -0
  69. data/lib/corl_core/mixin/config/collection.rb +53 -0
  70. data/lib/corl_core/mixin/config/ops.rb +53 -0
  71. data/lib/corl_core/mixin/config/options.rb +39 -0
  72. data/lib/corl_core/mixin/lookup.rb +196 -0
  73. data/lib/corl_core/mixin/macro/object_interface.rb +361 -0
  74. data/lib/corl_core/mixin/macro/plugin_interface.rb +380 -0
  75. data/lib/corl_core/mixin/settings.rb +46 -0
  76. data/lib/corl_core/mixin/sub_config.rb +148 -0
  77. data/lib/corl_core/mod/hash.rb +29 -0
  78. data/lib/corl_core/mod/hiera_backend.rb +63 -0
  79. data/lib/corl_core/plugin/action.rb +381 -0
  80. data/lib/corl_core/plugin/base.rb +374 -0
  81. data/lib/corl_core/plugin/command.rb +98 -0
  82. data/lib/corl_core/plugin/configuration.rb +177 -0
  83. data/lib/corl_core/plugin/event.rb +53 -0
  84. data/lib/corl_core/plugin/extension.rb +12 -0
  85. data/lib/corl_core/plugin/machine.rb +266 -0
  86. data/lib/corl_core/plugin/network.rb +359 -0
  87. data/lib/corl_core/plugin/node.rb +904 -0
  88. data/lib/corl_core/plugin/project.rb +927 -0
  89. data/lib/corl_core/plugin/provisioner.rb +51 -0
  90. data/lib/corl_core/plugin/template.rb +80 -0
  91. data/lib/corl_core/plugin/translator.rb +38 -0
  92. data/lib/corl_core/util/cli.rb +352 -0
  93. data/lib/corl_core/util/data.rb +404 -0
  94. data/lib/corl_core/util/disk.rb +114 -0
  95. data/lib/corl_core/util/git.rb +47 -0
  96. data/lib/corl_core/util/interface.rb +319 -0
  97. data/lib/corl_core/util/liquid.rb +17 -0
  98. data/lib/corl_core/util/package.rb +93 -0
  99. data/lib/corl_core/util/shell.rb +239 -0
  100. data/lib/corl_core/util/ssh.rb +286 -0
  101. data/lib/facter/corl_config_ready.rb +13 -0
  102. data/lib/facter/corl_exists.rb +15 -0
  103. data/lib/facter/corl_network.rb +17 -0
  104. data/lib/hiera/corl_logger.rb +18 -0
  105. data/lib/puppet/indirector/corl.rb +27 -0
  106. data/lib/puppet/indirector/data_binding/corl.rb +6 -0
  107. data/lib/puppet/parser/functions/config_initialized.rb +26 -0
  108. data/lib/puppet/parser/functions/corl_include.rb +44 -0
  109. data/lib/puppet/parser/functions/corl_resources.rb +58 -0
  110. data/lib/puppet/parser/functions/deep_merge.rb +21 -0
  111. data/lib/puppet/parser/functions/ensure.rb +29 -0
  112. data/lib/puppet/parser/functions/file_exists.rb +19 -0
  113. data/lib/puppet/parser/functions/global_array.rb +35 -0
  114. data/lib/puppet/parser/functions/global_hash.rb +35 -0
  115. data/lib/puppet/parser/functions/global_options.rb +23 -0
  116. data/lib/puppet/parser/functions/global_param.rb +43 -0
  117. data/lib/puppet/parser/functions/interpolate.rb +26 -0
  118. data/lib/puppet/parser/functions/is_false.rb +21 -0
  119. data/lib/puppet/parser/functions/is_true.rb +21 -0
  120. data/lib/puppet/parser/functions/module_array.rb +38 -0
  121. data/lib/puppet/parser/functions/module_hash.rb +38 -0
  122. data/lib/puppet/parser/functions/module_options.rb +23 -0
  123. data/lib/puppet/parser/functions/module_param.rb +48 -0
  124. data/lib/puppet/parser/functions/name.rb +21 -0
  125. data/lib/puppet/parser/functions/render.rb +33 -0
  126. data/lib/puppet/parser/functions/value.rb +21 -0
  127. data/locales/en.yml +232 -0
  128. data/spec/corl_core/interface_spec.rb +489 -0
  129. data/spec/corl_mock_input.rb +29 -0
  130. data/spec/corl_test_kernel.rb +22 -0
  131. data/spec/spec_helper.rb +15 -0
  132. metadata +406 -0
@@ -0,0 +1,266 @@
1
+
2
+ module CORL
3
+ module Plugin
4
+ class Machine < Base
5
+
6
+ #-----------------------------------------------------------------------------
7
+ # Machine plugin interface
8
+
9
+ def normalize
10
+ myself.plugin_name = nil if plugin_name.to_s == plugin_provider.to_s
11
+ end
12
+
13
+ #-----------------------------------------------------------------------------
14
+ # Checks
15
+
16
+ def created?
17
+ false
18
+ end
19
+
20
+ #---
21
+
22
+ def running?
23
+ ( created? && false )
24
+ end
25
+
26
+ #-----------------------------------------------------------------------------
27
+ # Property accessors / modifiers
28
+
29
+ def node
30
+ plugin_parent
31
+ end
32
+
33
+ def node=node
34
+ myself.plugin_parent = node
35
+ end
36
+
37
+ #---
38
+
39
+ def state
40
+ nil
41
+ end
42
+
43
+ #---
44
+
45
+ def hostname
46
+ nil
47
+ end
48
+
49
+ #---
50
+
51
+ def public_ip
52
+ nil
53
+ end
54
+
55
+ #---
56
+
57
+ def private_ip
58
+ nil
59
+ end
60
+
61
+ #---
62
+
63
+ def machine_types
64
+ []
65
+ end
66
+
67
+ #---
68
+
69
+ def machine_type
70
+ nil
71
+ end
72
+
73
+ #---
74
+
75
+ def images
76
+ []
77
+ end
78
+
79
+ #---
80
+
81
+ def image
82
+ nil
83
+ end
84
+
85
+ #-----------------------------------------------------------------------------
86
+ # Management
87
+
88
+ def load
89
+ success = true
90
+
91
+ logger.debug("Loading #{plugin_provider} machine: #{name}")
92
+ success = yield if block_given?
93
+
94
+ logger.warn("There was an error loading the machine #{name}") unless success
95
+ success
96
+ end
97
+
98
+ #---
99
+
100
+ def create(options = {})
101
+ success = true
102
+
103
+ if created?
104
+ logger.debug("Machine #{name} already exists")
105
+ else
106
+ logger.debug("Creating #{plugin_provider} machine with: #{options.inspect}")
107
+ config = Config.ensure(options)
108
+ success = yield(config) if block_given?
109
+ end
110
+
111
+ logger.warn("There was an error creating the machine #{name}") unless success
112
+ success
113
+ end
114
+
115
+ #---
116
+
117
+ def download(remote_path, local_path, options = {})
118
+ success = true
119
+
120
+ if running?
121
+ logger.debug("Downloading #{local_path} from #{remote_path} on #{plugin_provider} machine with: #{options.inspect}")
122
+ config = Config.ensure(options)
123
+ success = yield(config, success) if block_given?
124
+ else
125
+ logger.debug("Machine #{name} is not running")
126
+ end
127
+
128
+ logger.warn("There was an error downloading from the machine #{name}") unless success
129
+ success
130
+ end
131
+
132
+ #---
133
+
134
+ def upload(local_path, remote_path, options = {})
135
+ success = true
136
+
137
+ if running?
138
+ logger.debug("Uploading #{local_path} to #{remote_path} on #{plugin_provider} machine with: #{options.inspect}")
139
+ config = Config.ensure(options)
140
+ success = yield(config, success) if block_given?
141
+ else
142
+ logger.debug("Machine #{name} is not running")
143
+ end
144
+
145
+ logger.warn("There was an error uploading to the machine #{name}") unless success
146
+ success
147
+ end
148
+
149
+ #---
150
+
151
+ def exec(commands, options = {})
152
+ results = []
153
+
154
+ if running?
155
+ logger.debug("Executing command on #{plugin_provider} machine with: #{options.inspect}")
156
+ config = Config.ensure(options)
157
+ results = yield(config, results) if block_given?
158
+ else
159
+ logger.debug("Machine #{name} is not running")
160
+ end
161
+
162
+ logger.warn("There was an error executing command on the machine #{name}") unless results
163
+ results
164
+ end
165
+
166
+ #---
167
+
168
+ def start(options = {})
169
+ success = true
170
+
171
+ if running?
172
+ logger.debug("Machine #{name} is already running")
173
+ else
174
+ logger.debug("Starting #{plugin_provider} machine with: #{options.inspect}")
175
+
176
+ if created?
177
+ config = Config.ensure(options)
178
+ success = yield(config) if block_given?
179
+ else
180
+ logger.debug("Machine #{name} does not yet exist")
181
+ success = create(options)
182
+ end
183
+ end
184
+
185
+ logger.warn("There was an error starting the machine #{name}") unless success
186
+ success
187
+ end
188
+
189
+ #---
190
+
191
+ def reload(options = {})
192
+ success = true
193
+
194
+ if created?
195
+ logger.debug("Reloading #{plugin_provider} machine with: #{options.inspect}")
196
+ config = Config.ensure(options)
197
+ success = yield(config) if block_given?
198
+ else
199
+ logger.debug("Machine #{name} does not yet exist")
200
+ end
201
+
202
+ logger.warn("There was an error reloading the machine #{name}") unless success
203
+ success
204
+ end
205
+
206
+ #---
207
+
208
+ def create_image(options = {})
209
+ success = true
210
+
211
+ if running?
212
+ logger.debug("Creating image of #{plugin_provider} machine with: #{options.inspect}")
213
+ config = Config.ensure(options)
214
+ success = yield(config) if block_given?
215
+ else
216
+ logger.debug("Machine #{name} is not running")
217
+ end
218
+
219
+ logger.warn("There was an error creating an image of the machine #{name}") unless success
220
+ success
221
+ end
222
+
223
+ #---
224
+
225
+ def stop(options = {})
226
+ success = true
227
+
228
+ if running?
229
+ logger.debug("Stopping #{plugin_provider} machine with: #{options.inspect}")
230
+ config = Config.ensure(options)
231
+ success = yield(config) if block_given?
232
+ else
233
+ logger.debug("Machine #{name} is not running")
234
+ end
235
+
236
+ logger.warn("There was an error stopping the machine #{name}") unless success
237
+ success
238
+ end
239
+
240
+ #---
241
+
242
+ def destroy(options = {})
243
+ success = true
244
+
245
+ if created?
246
+ logger.debug("Destroying #{plugin_provider} machine with: #{options.inspect}")
247
+ config = Config.ensure(options)
248
+ success = yield(config) if block_given?
249
+ else
250
+ logger.debug("Machine #{name} does not yet exist")
251
+ end
252
+
253
+ logger.warn("There was an error destroying the machine #{name}") unless success
254
+ success
255
+ end
256
+
257
+ #-----------------------------------------------------------------------------
258
+ # Utilities
259
+
260
+ def translate_state(state)
261
+ return string(state).downcase.to_sym if status
262
+ :unknown
263
+ end
264
+ end
265
+ end
266
+ end
@@ -0,0 +1,359 @@
1
+
2
+ module CORL
3
+ module Plugin
4
+ class Network < Base
5
+
6
+ init_plugin_collection
7
+
8
+ #-----------------------------------------------------------------------------
9
+ # Cloud plugin interface
10
+
11
+ def normalize
12
+ super
13
+
14
+ logger.info("Initializing sub configuration from source with: #{myself._export.inspect}")
15
+ myself.config = CORL.configuration(Config.new(myself._export))
16
+ end
17
+
18
+ #-----------------------------------------------------------------------------
19
+ # Checks
20
+
21
+ def has_nodes?(provider = nil)
22
+ node_config(provider).export.empty? ? false : true
23
+ end
24
+
25
+ #-----------------------------------------------------------------------------
26
+ # Property accessors / modifiers
27
+
28
+ plugin_collection :node
29
+
30
+ #---
31
+
32
+ def home
33
+ extension_set(:home, ( ENV['USER'] == 'root' ? '/root' : ENV['HOME'] ))
34
+ end
35
+
36
+ #---
37
+
38
+ def remote(name)
39
+ config.remote(name)
40
+ end
41
+
42
+ def set_remote(name, location)
43
+ config.set_remote(name, location)
44
+ end
45
+
46
+ #---
47
+
48
+ def node_groups
49
+ groups = {}
50
+
51
+ each_node_config! do |provider, name, info|
52
+ search_node(provider, name, :groups, [], :array).each do |group|
53
+ group = group.to_sym
54
+ groups[group] = [] unless groups.has_key?(group)
55
+ groups[group] << { :provider => provider, :name => node_name }
56
+ end
57
+ end
58
+ groups
59
+ end
60
+
61
+ #---
62
+
63
+ def node_info(references, default_provider = nil)
64
+ groups = node_groups
65
+ node_info = {}
66
+
67
+ default_provider = Manager.connection.type_default(:node) if default_provider.nil?
68
+
69
+ references.each do |reference|
70
+ info = Plugin::Node.translate_reference(reference)
71
+ info = { :provider => default_provider, :name => reference } unless info
72
+ name = info[:name].to_sym
73
+
74
+ # Check for group membership
75
+ if groups.has_key?(name)
76
+ groups[name].each do |member_info|
77
+ provider = member_info[:provider].to_sym
78
+
79
+ node_info[provider] = [] unless node_info.has_key?(provider)
80
+ node_info[provider] << member_info[:name]
81
+ end
82
+ else
83
+ # Not a group
84
+ provider = info[:provider].to_sym
85
+
86
+ if node_config.export.has_key?(provider)
87
+ node_found = false
88
+
89
+ each_node_config(provider) do |node_provider, node_name, node|
90
+ if node_name == name
91
+ node_info[node_provider] = [] unless node_info.has_key?(node_provider)
92
+ node_info[node_provider] << node_name
93
+ node_found = true
94
+ break
95
+ end
96
+ end
97
+
98
+ unless node_found
99
+ # TODO: Error or something?
100
+ end
101
+ end
102
+ end
103
+ end
104
+ node_info
105
+ end
106
+
107
+ #---
108
+
109
+ def node_by_ip(public_ip)
110
+ each_node_config! do |provider, name, info|
111
+ return node(provider, name) if info[:public_ip] == public_ip
112
+ end
113
+ nil
114
+ end
115
+
116
+ #---
117
+
118
+ def local_node
119
+ ip_address = lookup(:ipaddress)
120
+ local_node = node_by_ip(ip_address)
121
+
122
+ if local_node.nil?
123
+ name = Util::Data.ensure_value(lookup(:hostname), ip_address)
124
+ local_node = CORL.node(name, extended_config(:local_node).import({ :meta => { :parent => myself }}), :local)
125
+ else
126
+ local_node.localize
127
+ end
128
+ local_node
129
+ end
130
+
131
+ #---
132
+
133
+ def nodes_by_reference(references, default_provider = nil)
134
+ nodes = []
135
+
136
+ node_info(references, default_provider).each do |provider, names|
137
+ names.each do |name|
138
+ nodes << node(provider, name)
139
+ end
140
+ end
141
+ nodes
142
+ end
143
+
144
+ #---
145
+
146
+ def test_node(provider)
147
+ CORL.node(:test, { :meta => { :parent => myself } }, provider)
148
+ end
149
+
150
+ #-----------------------------------------------------------------------------
151
+ # Operations
152
+
153
+ def load(options = {})
154
+ config.load(options)
155
+ end
156
+
157
+ #---
158
+
159
+ def save(options = {})
160
+ config.save(options)
161
+ end
162
+
163
+ #---
164
+
165
+ def attach_files(type, name, files, options = {})
166
+ attach_config = Config.ensure(options).import({ :type => :file })
167
+ included_files = []
168
+ files = [ files ] unless files.is_a?(Array)
169
+
170
+ files.each do |file|
171
+ if file
172
+ attached_file = config.attach(type, name, file, attach_config)
173
+ included_files << attached_file unless attached_file.nil?
174
+ end
175
+ end
176
+ included_files
177
+ end
178
+
179
+ #---
180
+
181
+ def attach_data(type, name, data, options = {})
182
+ attach_config = Config.ensure(options).import({ :type => :source })
183
+ attached_data = nil
184
+
185
+ if data.is_a?(String)
186
+ attached_data = config.attach(type, name, file, attach_config)
187
+ end
188
+ attached_data
189
+ end
190
+
191
+ #---
192
+
193
+ def attach_keys(node, keypair)
194
+ save_config = { :pull => false, :push => false }
195
+ private_key = attach_data(:keys, "#{node.public_ip}-id_#{keypair.type}", keypair.encrypted_key)
196
+ public_key = attach_data(:keys, "#{node.public_ip}-id_#{keypair.type}.pub", keypair.ssh_key)
197
+
198
+ if private_key && public_key
199
+ save_config[:files] = [ private_key, public_key ]
200
+
201
+ node[:private_key] = private_key
202
+ node[:public_key] = public_key
203
+
204
+ save_config[:message] = "Updating SSH keys for node #{node.plugin_name} (#{node.public_ip})"
205
+ node.save(extended_config(:key_save, save_config))
206
+ else
207
+ false
208
+ end
209
+ end
210
+
211
+ #---
212
+
213
+ def add_node(provider, name, options = {})
214
+ config = Config.ensure(options)
215
+
216
+ keypair = config.delete(:keypair, nil)
217
+ return false unless keypair && keypair.is_a?(Util::SSH::Keypair)
218
+
219
+ remote_name = config.delete(:remote, :edit)
220
+ dbg(config, 'node add configuration')
221
+
222
+ # Set node data
223
+ #node = set_node(provider, name, config)
224
+ #hook_config = { :node => node, :remote => remote_name, :seed => seed_project, :config => config }
225
+ success = true
226
+
227
+ #yield(:preprocess, hook_config) if block_given?
228
+
229
+ #if ! node.local? && attach_keys(node, keypair) && extension_check(:add_node, hook_config)
230
+ # # Create new node / machine
231
+ # success = node.create do |op, data|
232
+ # data = yield("create_#{op}".to_sym, data) if block_given?
233
+ # data
234
+ # end
235
+
236
+ # if success
237
+ # # Bootstrap new machine
238
+ # success = node.bootstrap(home, extended_config(:bootstrap, config)) do |op, data|
239
+ # data = yield("bootstrap_#{op}".to_sym, data) if block_given?
240
+ # data
241
+ # end
242
+
243
+ # if success
244
+ # save_config = { :commit => true, :remote => remote_name, :push => true }
245
+
246
+ # if seed_project && remote_name
247
+ # # Reset project remote
248
+ # seed_info = Plugin::Project.translate_reference(seed_project)
249
+
250
+ # if seed_info
251
+ # seed_url = seed_info[:url]
252
+ # seed_branch = seed_info[:revision] if seed_info[:revision]
253
+ # else
254
+ # seed_url = seed_project
255
+ # end
256
+ # set_remote(:origin, seed_url) if remote_name.to_sym == :edit
257
+ # set_remote(remote_name, seed_url)
258
+ # save_config[:pull] = false
259
+ # end
260
+
261
+ # # Save network changes (preliminary)
262
+ # success = node.save(extended_config(:node_save, save_config))
263
+
264
+ # if success && seed_project
265
+ # # Seed machine with remote project reference
266
+ # result = node.seed({
267
+ # :net_provider => plugin_provider,
268
+ # :project_reference => seed_project,
269
+ # :project_branch => seed_branch
270
+ # }) do |op, data|
271
+ # yield("seed_#{op}".to_sym, data)
272
+ # end
273
+ # success = result.status == code.success
274
+ # end
275
+
276
+ # if success
277
+ # # Update local network project
278
+ # end
279
+ # end
280
+ # end
281
+ #end
282
+
283
+ success
284
+ end
285
+
286
+ #---
287
+
288
+ def remove_node(provider, name = nil)
289
+ status = CORL.code.success
290
+
291
+ if name.nil?
292
+ nodes(provider).each do |node_name, node|
293
+ sub_status = remove_node(provider, node_name)
294
+ status = sub_status unless status == sub_status
295
+ end
296
+ else
297
+ node = node(provider, name)
298
+
299
+ unless node.local?
300
+ # Stop node
301
+ status = node.run(:stop)
302
+ end
303
+
304
+ if status == CORL.code.success
305
+ delete_node(provider, name)
306
+ else
307
+ ui.warn("Stopping #{provider} node #{name} failed")
308
+ end
309
+ end
310
+
311
+ status
312
+ end
313
+
314
+ #-----------------------------------------------------------------------------
315
+ # Utilities
316
+
317
+ def each_node_config(provider = nil)
318
+ node_config.export.each do |node_provider, nodes|
319
+ if provider.nil? || provider == node_provider
320
+ nodes.each do |name, info|
321
+ yield(node_provider, name, info)
322
+ end
323
+ end
324
+ end
325
+ end
326
+
327
+ #---
328
+
329
+ execute_block_on_receiver :batch
330
+
331
+ def batch(node_references, default_provider = nil, parallel = true, &code)
332
+ success = true
333
+
334
+ if has_nodes? && ! node_references.empty?
335
+ # Execute action on selected nodes
336
+ nodes = nodes_by_reference(node_references, default_provider)
337
+
338
+ if parallel
339
+ values = []
340
+ nodes.each do |node|
341
+ values << Celluloid::Future.new(node, &code)
342
+ end
343
+ values = values.map { |future| future.value }
344
+ success = false if values.include?(false)
345
+ else
346
+ nodes.each do |node|
347
+ proc_success = code.call(node)
348
+ if proc_success == false
349
+ success = false
350
+ break
351
+ end
352
+ end
353
+ end
354
+ end
355
+ success
356
+ end
357
+ end
358
+ end
359
+ end