chef-provisioning-fog 0.14.0 → 0.15.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.
- checksums.yaml +4 -4
- data/LICENSE +201 -201
- data/README.md +3 -3
- data/Rakefile +6 -6
- data/lib/chef/provider/fog_key_pair.rb +266 -266
- data/lib/chef/provisioning/driver_init/fog.rb +3 -3
- data/lib/chef/provisioning/fog_driver/driver.rb +736 -709
- data/lib/chef/provisioning/fog_driver/providers/aws.rb +492 -492
- data/lib/chef/provisioning/fog_driver/providers/aws/credentials.rb +115 -115
- data/lib/chef/provisioning/fog_driver/providers/cloudstack.rb +44 -44
- data/lib/chef/provisioning/fog_driver/providers/digitalocean.rb +136 -136
- data/lib/chef/provisioning/fog_driver/providers/google.rb +85 -84
- data/lib/chef/provisioning/fog_driver/providers/joyent.rb +63 -59
- data/lib/chef/provisioning/fog_driver/providers/openstack.rb +117 -41
- data/lib/chef/provisioning/fog_driver/providers/rackspace.rb +42 -42
- data/lib/chef/provisioning/fog_driver/providers/softlayer.rb +36 -36
- data/lib/chef/provisioning/fog_driver/providers/vcair.rb +409 -376
- data/lib/chef/provisioning/fog_driver/providers/xenserver.rb +210 -0
- data/lib/chef/provisioning/fog_driver/recipe_dsl.rb +32 -32
- data/lib/chef/provisioning/fog_driver/version.rb +7 -7
- data/lib/chef/resource/fog_key_pair.rb +34 -34
- data/spec/spec_helper.rb +18 -18
- data/spec/support/aws/config-file.csv +2 -2
- data/spec/support/aws/ini-file.ini +10 -10
- data/spec/support/chef_metal_fog/providers/testdriver.rb +16 -16
- data/spec/unit/chef/provisioning/fog_driver/driver_spec.rb +71 -0
- data/spec/unit/fog_driver_spec.rb +32 -32
- data/spec/unit/providers/aws/credentials_spec.rb +45 -45
- data/spec/unit/providers/rackspace_spec.rb +16 -16
- metadata +5 -3
@@ -1,42 +1,42 @@
|
|
1
|
-
# fog:Rackspace:https://identity.api.rackspacecloud.com/v2.0
|
2
|
-
class Chef
|
3
|
-
module Provisioning
|
4
|
-
module FogDriver
|
5
|
-
module Providers
|
6
|
-
class Rackspace < FogDriver::Driver
|
7
|
-
|
8
|
-
Driver.register_provider_class('Rackspace', FogDriver::Providers::Rackspace)
|
9
|
-
|
10
|
-
def creator
|
11
|
-
compute_options[:rackspace_username]
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.compute_options_for(provider, id, config)
|
15
|
-
new_compute_options = {}
|
16
|
-
new_compute_options[:provider] = provider
|
17
|
-
new_config = { :driver_options => { :compute_options => new_compute_options }}
|
18
|
-
new_defaults = {
|
19
|
-
:driver_options => { :compute_options => {} },
|
20
|
-
:machine_options => { :bootstrap_options => {} }
|
21
|
-
}
|
22
|
-
result = Cheffish::MergedConfig.new(new_config, config, new_defaults)
|
23
|
-
|
24
|
-
new_compute_options[:rackspace_auth_url] = id if (id && id != '')
|
25
|
-
credential = Fog.credentials
|
26
|
-
|
27
|
-
new_compute_options[:rackspace_username] ||= credential[:rackspace_username]
|
28
|
-
new_compute_options[:rackspace_api_key] ||= credential[:rackspace_api_key]
|
29
|
-
new_compute_options[:rackspace_auth_url] ||= credential[:rackspace_auth_url]
|
30
|
-
new_compute_options[:rackspace_region] ||= credential[:rackspace_region]
|
31
|
-
new_compute_options[:rackspace_endpoint] ||= credential[:rackspace_endpoint]
|
32
|
-
|
33
|
-
id = result[:driver_options][:compute_options][:rackspace_auth_url]
|
34
|
-
|
35
|
-
[result, id]
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
1
|
+
# fog:Rackspace:https://identity.api.rackspacecloud.com/v2.0
|
2
|
+
class Chef
|
3
|
+
module Provisioning
|
4
|
+
module FogDriver
|
5
|
+
module Providers
|
6
|
+
class Rackspace < FogDriver::Driver
|
7
|
+
|
8
|
+
Driver.register_provider_class('Rackspace', FogDriver::Providers::Rackspace)
|
9
|
+
|
10
|
+
def creator
|
11
|
+
compute_options[:rackspace_username]
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.compute_options_for(provider, id, config)
|
15
|
+
new_compute_options = {}
|
16
|
+
new_compute_options[:provider] = provider
|
17
|
+
new_config = { :driver_options => { :compute_options => new_compute_options }}
|
18
|
+
new_defaults = {
|
19
|
+
:driver_options => { :compute_options => {} },
|
20
|
+
:machine_options => { :bootstrap_options => {} }
|
21
|
+
}
|
22
|
+
result = Cheffish::MergedConfig.new(new_config, config, new_defaults)
|
23
|
+
|
24
|
+
new_compute_options[:rackspace_auth_url] = id if (id && id != '')
|
25
|
+
credential = Fog.credentials
|
26
|
+
|
27
|
+
new_compute_options[:rackspace_username] ||= credential[:rackspace_username]
|
28
|
+
new_compute_options[:rackspace_api_key] ||= credential[:rackspace_api_key]
|
29
|
+
new_compute_options[:rackspace_auth_url] ||= credential[:rackspace_auth_url]
|
30
|
+
new_compute_options[:rackspace_region] ||= credential[:rackspace_region]
|
31
|
+
new_compute_options[:rackspace_endpoint] ||= credential[:rackspace_endpoint]
|
32
|
+
|
33
|
+
id = result[:driver_options][:compute_options][:rackspace_auth_url]
|
34
|
+
|
35
|
+
[result, id]
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -1,36 +1,36 @@
|
|
1
|
-
class Chef
|
2
|
-
module Provisioning
|
3
|
-
module FogDriver
|
4
|
-
module Providers
|
5
|
-
class SoftLayer < FogDriver::Driver
|
6
|
-
Driver.register_provider_class('SoftLayer', FogDriver::Providers::SoftLayer)
|
7
|
-
|
8
|
-
def creator
|
9
|
-
compute_options[:softlayer_username]
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.compute_options_for(provider, id, config)
|
13
|
-
new_compute_options = {}
|
14
|
-
new_compute_options[:provider] = provider
|
15
|
-
new_config = { :driver_options => { :compute_options => new_compute_options }}
|
16
|
-
new_defaults = {
|
17
|
-
:driver_options => { :compute_options => {} },
|
18
|
-
:machine_options => { :bootstrap_options => {} }
|
19
|
-
}
|
20
|
-
result = Cheffish::MergedConfig.new(new_config, config, new_defaults)
|
21
|
-
|
22
|
-
credential = Fog.credentials
|
23
|
-
|
24
|
-
new_compute_options[:softlayer_username] ||= credential[:softlayer_username]
|
25
|
-
new_compute_options[:softlayer_api_key] ||= credential[:softlayer_api_key]
|
26
|
-
|
27
|
-
id = result[:driver_options][:compute_options][:softlayer_auth_url]
|
28
|
-
|
29
|
-
[result, id]
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
1
|
+
class Chef
|
2
|
+
module Provisioning
|
3
|
+
module FogDriver
|
4
|
+
module Providers
|
5
|
+
class SoftLayer < FogDriver::Driver
|
6
|
+
Driver.register_provider_class('SoftLayer', FogDriver::Providers::SoftLayer)
|
7
|
+
|
8
|
+
def creator
|
9
|
+
compute_options[:softlayer_username]
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.compute_options_for(provider, id, config)
|
13
|
+
new_compute_options = {}
|
14
|
+
new_compute_options[:provider] = provider
|
15
|
+
new_config = { :driver_options => { :compute_options => new_compute_options }}
|
16
|
+
new_defaults = {
|
17
|
+
:driver_options => { :compute_options => {} },
|
18
|
+
:machine_options => { :bootstrap_options => {} }
|
19
|
+
}
|
20
|
+
result = Cheffish::MergedConfig.new(new_config, config, new_defaults)
|
21
|
+
|
22
|
+
credential = Fog.credentials
|
23
|
+
|
24
|
+
new_compute_options[:softlayer_username] ||= credential[:softlayer_username]
|
25
|
+
new_compute_options[:softlayer_api_key] ||= credential[:softlayer_api_key]
|
26
|
+
|
27
|
+
id = result[:driver_options][:compute_options][:softlayer_auth_url]
|
28
|
+
|
29
|
+
[result, id]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
@@ -1,376 +1,409 @@
|
|
1
|
-
# fog:Vcair:<client id>
|
2
|
-
class Chef
|
3
|
-
module Provisioning
|
4
|
-
module FogDriver
|
5
|
-
module Providers
|
6
|
-
class Vcair < FogDriver::Driver
|
7
|
-
Driver.register_provider_class('Vcair', FogDriver::Providers::Vcair)
|
8
|
-
|
9
|
-
def creator
|
10
|
-
Chef::Config[:knife][:vcair_username]
|
11
|
-
end
|
12
|
-
|
13
|
-
def compute
|
14
|
-
@compute ||= begin
|
15
|
-
Chef::Log.debug("vcair_username #{Chef::Config[:knife][:vcair_username]}")
|
16
|
-
Chef::Log.debug("vcair_org #{Chef::Config[:knife][:vcair_org]}")
|
17
|
-
Chef::Log.debug("vcair_api_host #{Chef::Config[:knife][:vcair_api_host]}")
|
18
|
-
#Chef::Log.debug("vcair_api_version #{Chef::Config[:knife][:vcair_api_version]}")
|
19
|
-
Chef::Log.debug("vcair_show_progress #{Chef::Config[:knife][:vcair_show_progress]}")
|
20
|
-
|
21
|
-
username = [
|
22
|
-
Chef::Config[:knife][:vcair_username],
|
23
|
-
Chef::Config[:knife][:vcair_org]
|
24
|
-
].join('@')
|
25
|
-
|
26
|
-
@auth_params = {
|
27
|
-
:provider => 'vclouddirector', #TODO: see compute_options_for, and grab else where
|
28
|
-
:vcloud_director_username => username,
|
29
|
-
:vcloud_director_password => Chef::Config[:knife][:vcair_password],
|
30
|
-
:vcloud_director_host => Chef::Config[:knife][:vcair_api_host],
|
31
|
-
#:vcair_api_host => Chef::Config[:knife][:vcair_api_host],
|
32
|
-
:vcloud_director_api_version => Chef::Config[:knife][:vcair_api_version],
|
33
|
-
:vcloud_director_show_progress => false
|
34
|
-
}
|
35
|
-
|
36
|
-
Fog::Compute.new(@auth_params)
|
37
|
-
rescue Excon::Errors::Unauthorized => e
|
38
|
-
error_message = "Connection failure, please check your username and password."
|
39
|
-
Chef::Log.error(error_message)
|
40
|
-
raise "#{e.message}. #{error_message}"
|
41
|
-
rescue Excon::Errors::SocketError => e
|
42
|
-
error_message = "Connection failure, please check your authentication URL."
|
43
|
-
Chef::Log.error(error_message)
|
44
|
-
raise "#{e.message}. #{error_message}"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
|
49
|
-
def create_many_servers(num_servers, bootstrap_options, parallelizer)
|
50
|
-
parallelizer.parallelize(1.upto(num_servers)) do |i|
|
51
|
-
clean_bootstrap_options = Marshal.load(Marshal.dump(bootstrap_options)) # Prevent destructive operations on bootstrap_options.
|
52
|
-
vm=nil
|
53
|
-
begin
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
nil
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
#
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
@
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
end
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
1
|
+
# fog:Vcair:<client id>
|
2
|
+
class Chef
|
3
|
+
module Provisioning
|
4
|
+
module FogDriver
|
5
|
+
module Providers
|
6
|
+
class Vcair < FogDriver::Driver
|
7
|
+
Driver.register_provider_class('Vcair', FogDriver::Providers::Vcair)
|
8
|
+
|
9
|
+
def creator
|
10
|
+
Chef::Config[:knife][:vcair_username]
|
11
|
+
end
|
12
|
+
|
13
|
+
def compute
|
14
|
+
@compute ||= begin
|
15
|
+
Chef::Log.debug("vcair_username #{Chef::Config[:knife][:vcair_username]}")
|
16
|
+
Chef::Log.debug("vcair_org #{Chef::Config[:knife][:vcair_org]}")
|
17
|
+
Chef::Log.debug("vcair_api_host #{Chef::Config[:knife][:vcair_api_host]}")
|
18
|
+
#Chef::Log.debug("vcair_api_version #{Chef::Config[:knife][:vcair_api_version]}")
|
19
|
+
Chef::Log.debug("vcair_show_progress #{Chef::Config[:knife][:vcair_show_progress]}")
|
20
|
+
|
21
|
+
username = [
|
22
|
+
Chef::Config[:knife][:vcair_username],
|
23
|
+
Chef::Config[:knife][:vcair_org]
|
24
|
+
].join('@')
|
25
|
+
|
26
|
+
@auth_params = {
|
27
|
+
:provider => 'vclouddirector', #TODO: see compute_options_for, and grab else where
|
28
|
+
:vcloud_director_username => username,
|
29
|
+
:vcloud_director_password => Chef::Config[:knife][:vcair_password],
|
30
|
+
:vcloud_director_host => Chef::Config[:knife][:vcair_api_host],
|
31
|
+
#:vcair_api_host => Chef::Config[:knife][:vcair_api_host],
|
32
|
+
:vcloud_director_api_version => Chef::Config[:knife][:vcair_api_version],
|
33
|
+
:vcloud_director_show_progress => false
|
34
|
+
}
|
35
|
+
|
36
|
+
Fog::Compute.new(@auth_params)
|
37
|
+
rescue Excon::Errors::Unauthorized => e
|
38
|
+
error_message = "Connection failure, please check your username and password."
|
39
|
+
Chef::Log.error(error_message)
|
40
|
+
raise "#{e.message}. #{error_message}"
|
41
|
+
rescue Excon::Errors::SocketError => e
|
42
|
+
error_message = "Connection failure, please check your authentication URL."
|
43
|
+
Chef::Log.error(error_message)
|
44
|
+
raise "#{e.message}. #{error_message}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def create_many_servers(num_servers, bootstrap_options, parallelizer)
|
50
|
+
parallelizer.parallelize(1.upto(num_servers)) do |i|
|
51
|
+
clean_bootstrap_options = Marshal.load(Marshal.dump(bootstrap_options)) # Prevent destructive operations on bootstrap_options.
|
52
|
+
vm=nil
|
53
|
+
begin
|
54
|
+
begin
|
55
|
+
instantiate(clean_bootstrap_options)
|
56
|
+
rescue Fog::Errors::Error => e
|
57
|
+
unless e.minor_error_code == "DUPLICATE_NAME"
|
58
|
+
# if it's already there, just use the current one
|
59
|
+
raise e
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
vapp = vdc.vapps.get_by_name(bootstrap_options[:name])
|
64
|
+
vm = vapp.vms.find {|v| v.vapp_name == bootstrap_options[:name]}
|
65
|
+
update_customization(clean_bootstrap_options, vm)
|
66
|
+
|
67
|
+
if bootstrap_options[:cpus]
|
68
|
+
vm.cpu = bootstrap_options[:cpus]
|
69
|
+
end
|
70
|
+
if bootstrap_options[:memory]
|
71
|
+
vm.memory = bootstrap_options[:memory]
|
72
|
+
end
|
73
|
+
update_network(bootstrap_options, vapp, vm)
|
74
|
+
|
75
|
+
rescue Excon::Errors::BadRequest => e
|
76
|
+
response = Chef::JSONCompat.from_json(e.response.body)
|
77
|
+
if response['badRequest']['code'] == 400
|
78
|
+
message = "Bad request (400): #{response['badRequest']['message']}"
|
79
|
+
Chef::Log.error(message)
|
80
|
+
else
|
81
|
+
message = "Unknown server error (#{response['badRequest']['code']}): #{response['badRequest']['message']}"
|
82
|
+
Chef::Log.error(message)
|
83
|
+
end
|
84
|
+
raise message
|
85
|
+
rescue Fog::Errors::Error => e
|
86
|
+
raise e.message
|
87
|
+
end
|
88
|
+
|
89
|
+
yield vm if block_given?
|
90
|
+
vm
|
91
|
+
|
92
|
+
end.to_a
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
def start_server(action_handler, machine_spec, server)
|
97
|
+
|
98
|
+
# If it is stopping, wait for it to get out of "stopping" transition state before starting
|
99
|
+
if server.status == 'stopping'
|
100
|
+
action_handler.report_progress "wait for #{machine_spec.name} (#{server.id} on #{driver_url}) to finish stopping ..."
|
101
|
+
# vCloud Air
|
102
|
+
# NOTE: vCloud Air Fog does not get server.status via http every time
|
103
|
+
server.wait_for { server.reload ; server.status != 'stopping' }
|
104
|
+
action_handler.report_progress "#{machine_spec.name} is now stopped"
|
105
|
+
end
|
106
|
+
|
107
|
+
# NOTE: vCloud Air Fog does not get server.status via http every time
|
108
|
+
server.reload
|
109
|
+
|
110
|
+
if server.status == 'off' or server.status != 'on'
|
111
|
+
action_handler.perform_action "start machine #{machine_spec.name} (#{server.id} on #{driver_url})" do
|
112
|
+
server.power_on
|
113
|
+
machine_spec.location['started_at'] = Time.now.to_i
|
114
|
+
end
|
115
|
+
machine_spec.save(action_handler)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
def server_for(machine_spec)
|
121
|
+
if machine_spec.location
|
122
|
+
vapp = vdc.vapps.get_by_name(machine_spec.name)
|
123
|
+
|
124
|
+
server = unless vapp.nil?
|
125
|
+
unless vapp.vms.first.nil?
|
126
|
+
vapp.vms.find{|vm| vm.id == machine_spec.location['server_id'] }
|
127
|
+
end
|
128
|
+
end
|
129
|
+
else
|
130
|
+
nil
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def servers_for(machine_specs)
|
135
|
+
result = {}
|
136
|
+
machine_specs.each do |machine_spec|
|
137
|
+
server_for(machine_spec)
|
138
|
+
end
|
139
|
+
result
|
140
|
+
end
|
141
|
+
|
142
|
+
def ssh_options_for(machine_spec, machine_options, server)
|
143
|
+
{ auth_methods: [ 'password' ],
|
144
|
+
timeout: (machine_options[:ssh_timeout] || 600),
|
145
|
+
password: machine_options[:ssh_password]
|
146
|
+
}.merge(machine_options[:ssh_options] || {})
|
147
|
+
end
|
148
|
+
|
149
|
+
def create_ssh_transport(machine_spec, machine_options, server)
|
150
|
+
ssh_options = ssh_options_for(machine_spec, machine_options, server)
|
151
|
+
username = machine_spec.location['ssh_username'] || default_ssh_username
|
152
|
+
options = {}
|
153
|
+
if machine_spec.location[:sudo] || (!machine_spec.location.has_key?(:sudo) && username != 'root')
|
154
|
+
options[:prefix] = 'sudo '
|
155
|
+
end
|
156
|
+
|
157
|
+
remote_host = nil
|
158
|
+
# vCloud Air networking is funky
|
159
|
+
#if machine_options[:use_private_ip_for_ssh] # vCloud Air probably needs private ip for now
|
160
|
+
if server.ip_address
|
161
|
+
remote_host = server.ip_address
|
162
|
+
else
|
163
|
+
raise "Server #{server.id} has no private or public IP address!"
|
164
|
+
end
|
165
|
+
|
166
|
+
#Enable pty by default
|
167
|
+
options[:ssh_pty_enable] = true
|
168
|
+
options[:ssh_gateway] = machine_spec.location['ssh_gateway'] if machine_spec.location.has_key?('ssh_gateway')
|
169
|
+
|
170
|
+
Transport::SSH.new(remote_host, username, ssh_options, options, config)
|
171
|
+
end
|
172
|
+
|
173
|
+
def ready_machine(action_handler, machine_spec, machine_options)
|
174
|
+
server = server_for(machine_spec)
|
175
|
+
if server.nil?
|
176
|
+
raise "Machine #{machine_spec.name} does not have a server associated with it, or server does not exist."
|
177
|
+
end
|
178
|
+
|
179
|
+
# Start the server if needed, and wait for it to start
|
180
|
+
start_server(action_handler, machine_spec, server)
|
181
|
+
wait_until_ready(action_handler, machine_spec, machine_options, server)
|
182
|
+
|
183
|
+
# Attach/detach floating IPs if necessary
|
184
|
+
# vCloud Air is funky for network. VM has to be powered off or you get this error:
|
185
|
+
# Primary NIC cannot be changed when the VM is not in Powered-off state
|
186
|
+
# See code in update_network()
|
187
|
+
#DISABLED: converge_floating_ips(action_handler, machine_spec, machine_options, server)
|
188
|
+
|
189
|
+
begin
|
190
|
+
wait_for_transport(action_handler, machine_spec, machine_options, server)
|
191
|
+
rescue Fog::Errors::TimeoutError
|
192
|
+
# Only ever reboot once, and only if it's been less than 10 minutes since we stopped waiting
|
193
|
+
if machine_spec.location['started_at'] || remaining_wait_time(machine_spec, machine_options) < -(10*60)
|
194
|
+
raise
|
195
|
+
else
|
196
|
+
# Sometimes (on EC2) the machine comes up but gets stuck or has
|
197
|
+
# some other problem. If this is the case, we restart the server
|
198
|
+
# to unstick it. Reboot covers a multitude of sins.
|
199
|
+
Chef::Log.warn "Machine #{machine_spec.name} (#{server.id} on #{driver_url}) was started but SSH did not come up. Rebooting machine in an attempt to unstick it ..."
|
200
|
+
restart_server(action_handler, machine_spec, server)
|
201
|
+
wait_until_ready(action_handler, machine_spec, machine_options, server)
|
202
|
+
wait_for_transport(action_handler, machine_spec, machine_options, server)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
machine_for(machine_spec, machine_options, server)
|
207
|
+
end
|
208
|
+
|
209
|
+
def org
|
210
|
+
@org ||= compute.organizations.get_by_name(Chef::Config[:knife][:vcair_org])
|
211
|
+
end
|
212
|
+
|
213
|
+
def vdc
|
214
|
+
if Chef::Config[:knife][:vcair_vdc]
|
215
|
+
@vdc ||= org.vdcs.get_by_name(Chef::Config[:knife][:vcair_vdc])
|
216
|
+
else
|
217
|
+
@vdc ||= org.vdcs.first
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def net
|
222
|
+
if Chef::Config[:knife][:vcair_net]
|
223
|
+
@net ||= org.networks.get_by_name(Chef::Config[:knife][:vcair_net])
|
224
|
+
else
|
225
|
+
# Grab first non-isolated (bridged, natRouted) network
|
226
|
+
@net ||= org.networks.find { |n| n if !n.fence_mode.match("isolated") }
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def template(bootstrap_options)
|
231
|
+
# TODO: find by catalog item ID and/or NAME
|
232
|
+
# TODO: add option to search just public and/or private catalogs
|
233
|
+
|
234
|
+
#TODO: maybe make a hash for caching
|
235
|
+
org.catalogs.map do |cat|
|
236
|
+
#cat.catalog_items.get_by_name(config_value(:image))
|
237
|
+
cat.catalog_items.get_by_name(bootstrap_options[:image_name])
|
238
|
+
end.compact.first
|
239
|
+
end
|
240
|
+
|
241
|
+
def instantiate(bootstrap_options)
|
242
|
+
begin
|
243
|
+
#node_name = config_value(:chef_node_name)
|
244
|
+
node_name = bootstrap_options[:name]
|
245
|
+
template(bootstrap_options).instantiate(
|
246
|
+
node_name,
|
247
|
+
vdc_id: vdc.id,
|
248
|
+
network_id: net.id,
|
249
|
+
description: "id:#{node_name}")
|
250
|
+
#rescue CloudExceptions::ServerCreateError => e
|
251
|
+
rescue => e
|
252
|
+
raise e
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
# Create a WinRM transport for a vCloud Air Vapp VM instance
|
257
|
+
# @param [Hash] machine_spec Machine-spec hash
|
258
|
+
# @param [Hash] machine_options Machine options (from the recipe)
|
259
|
+
# @param [Fog::Compute::Server] server A Fog mapping to the AWS instance
|
260
|
+
# @return [ChefMetal::Transport::WinRM] A WinRM Transport object to talk to the server
|
261
|
+
def create_winrm_transport(machine_spec, machine_options, server)
|
262
|
+
port = machine_spec.location['winrm_port'] || 5985
|
263
|
+
endpoint = "http://#{server.ip_address}:#{port}/wsman"
|
264
|
+
type = :plaintext
|
265
|
+
|
266
|
+
# Use basic HTTP auth - this is required for the WinRM setup we
|
267
|
+
# are using
|
268
|
+
# TODO: Improve that and support different users
|
269
|
+
options = {
|
270
|
+
:user => 'Administrator',
|
271
|
+
:pass => machine_options[:winrm_options][:password],
|
272
|
+
:disable_sspi => true,
|
273
|
+
:basic_auth_only => true
|
274
|
+
}
|
275
|
+
Chef::Provisioning::Transport::WinRM.new(endpoint, type, options, {})
|
276
|
+
end
|
277
|
+
|
278
|
+
def update_customization(bootstrap_options, server)
|
279
|
+
## Initialization before first power on.
|
280
|
+
custom=server.customization
|
281
|
+
|
282
|
+
if bootstrap_options[:customization_script]
|
283
|
+
custom.script = open(bootstrap_options[:customization_script]).read
|
284
|
+
end
|
285
|
+
|
286
|
+
bootstrap_options[:protocol] ||= case server.operating_system
|
287
|
+
when /Windows/
|
288
|
+
'winrm'
|
289
|
+
else
|
290
|
+
'ssh'
|
291
|
+
end
|
292
|
+
password = case bootstrap_options[:protocol]
|
293
|
+
when 'ssh'
|
294
|
+
bootstrap_options[:ssh_options][:password]
|
295
|
+
when 'winrm'
|
296
|
+
bootstrap_options[:winrm_options][:password]
|
297
|
+
end
|
298
|
+
|
299
|
+
if password
|
300
|
+
custom.admin_password = password
|
301
|
+
custom.admin_password_auto = false
|
302
|
+
custom.reset_password_required = false
|
303
|
+
else
|
304
|
+
# Password will be autogenerated
|
305
|
+
custom.admin_password_auto=true
|
306
|
+
# API will force password resets when auto is enabled
|
307
|
+
custom.reset_password_required = true
|
308
|
+
end
|
309
|
+
|
310
|
+
# TODO: Add support for admin_auto_logon to Fog
|
311
|
+
# c.admin_auto_logon_count = 100
|
312
|
+
# c.admin_auto_logon_enabled = true
|
313
|
+
|
314
|
+
# DNS and Windows want AlphaNumeric and dashes for hostnames
|
315
|
+
# Windows can only handle 15 character hostnames
|
316
|
+
# TODO: only change name for Windows!
|
317
|
+
#c.computer_name = config_value(:chef_node_name).gsub(/\W/,"-").slice(0..14)
|
318
|
+
custom.computer_name = bootstrap_options[:name].gsub(/\W/,"-").slice(0..14)
|
319
|
+
custom.enabled = true
|
320
|
+
custom.save
|
321
|
+
end
|
322
|
+
|
323
|
+
## vCloud Air
|
324
|
+
## TODO: make work with floating_ip junk currently used
|
325
|
+
## NOTE: current vCloud Air networking changes require VM to be powered off
|
326
|
+
def update_network(bootstrap_options, vapp, vm)
|
327
|
+
## TODO: allow user to specify network to connect to (see above net used)
|
328
|
+
# Define network connection for vm based on existing routed network
|
329
|
+
|
330
|
+
# vCloud Air inlining vapp() and vm()
|
331
|
+
#vapp = vdc.vapps.get_by_name(bootstrap_options[:name])
|
332
|
+
#vm = vapp.vms.find {|v| v.vapp_name == bootstrap_options[:name]}
|
333
|
+
return if vm.ip_address != "" # return if ip address is set, as this isn't a new VM
|
334
|
+
nc = vapp.network_config.find { |netc| netc if netc[:networkName].match(net.name) }
|
335
|
+
networks_config = [nc]
|
336
|
+
section = {PrimaryNetworkConnectionIndex: 0}
|
337
|
+
section[:NetworkConnection] = networks_config.compact.each_with_index.map do |network, i|
|
338
|
+
connection = {
|
339
|
+
network: network[:networkName],
|
340
|
+
needsCustomization: true,
|
341
|
+
NetworkConnectionIndex: i,
|
342
|
+
IsConnected: true
|
343
|
+
}
|
344
|
+
ip_address = network[:ip_address]
|
345
|
+
## TODO: support config options for allocation mode
|
346
|
+
#allocation_mode = network[:allocation_mode]
|
347
|
+
#allocation_mode = 'manual' if ip_address
|
348
|
+
#allocation_mode = 'dhcp' unless %w{dhcp manual pool}.include?(allocation_mode)
|
349
|
+
#allocation_mode = 'POOL'
|
350
|
+
#connection[:Dns1] = dns1 if dns1
|
351
|
+
allocation_mode = 'pool'
|
352
|
+
connection[:IpAddressAllocationMode] = allocation_mode.upcase
|
353
|
+
connection[:IpAddress] = ip_address if ip_address
|
354
|
+
connection
|
355
|
+
end
|
356
|
+
|
357
|
+
## attach the network to the vm
|
358
|
+
nc_task = compute.put_network_connection_system_section_vapp(
|
359
|
+
vm.id,section).body
|
360
|
+
compute.process_task(nc_task)
|
361
|
+
end
|
362
|
+
|
363
|
+
def bootstrap_options_for(action_handler, machine_spec, machine_options)
|
364
|
+
bootstrap_options = symbolize_keys(machine_options[:bootstrap_options] || {})
|
365
|
+
|
366
|
+
bootstrap_options[:tags] = default_tags(machine_spec, bootstrap_options[:tags] || {})
|
367
|
+
bootstrap_options[:name] ||= machine_spec.name
|
368
|
+
|
369
|
+
bootstrap_options = bootstrap_options.merge(machine_options.configs[1])
|
370
|
+
bootstrap_options
|
371
|
+
end
|
372
|
+
|
373
|
+
def destroy_machine(action_handler, machine_spec, machine_options)
|
374
|
+
server = server_for(machine_spec)
|
375
|
+
if server && server.status != 'archive' # TODO: does vCloud Air do archive?
|
376
|
+
action_handler.perform_action "destroy machine #{machine_spec.name} (#{machine_spec.location['server_id']} at #{driver_url})" do
|
377
|
+
#NOTE: currently doing 1 vm for 1 vapp
|
378
|
+
vapp = vdc.vapps.get_by_name(machine_spec.name)
|
379
|
+
if vapp
|
380
|
+
vapp.power_off
|
381
|
+
vapp.undeploy
|
382
|
+
vapp.destroy
|
383
|
+
else
|
384
|
+
Chef::Log.warn "No VApp named '#{server_name}' was found."
|
385
|
+
end
|
386
|
+
end
|
387
|
+
end
|
388
|
+
machine_spec.location = nil
|
389
|
+
strategy = convergence_strategy_for(machine_spec, machine_options)
|
390
|
+
strategy.cleanup_convergence(action_handler, machine_spec)
|
391
|
+
end
|
392
|
+
|
393
|
+
def self.compute_options_for(provider, id, config)
|
394
|
+
new_compute_options = {}
|
395
|
+
new_compute_options[:provider] = 'vclouddirector'
|
396
|
+
new_config = { :driver_options => { :compute_options => new_compute_options }}
|
397
|
+
new_defaults = {
|
398
|
+
:driver_options => { :compute_options => {} },
|
399
|
+
:machine_options => { :bootstrap_options => {}, :ssh_options => {} }
|
400
|
+
}
|
401
|
+
result = Cheffish::MergedConfig.new(new_config, config, new_defaults)
|
402
|
+
|
403
|
+
[result, id]
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|
408
|
+
end
|
409
|
+
end
|