vagrant-softlayer 0.3.3 → 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.
- checksums.yaml +4 -4
- data/.gitignore +16 -16
- data/CHANGELOG.md +61 -49
- data/QUICKSTART.md +380 -376
- data/README.md +258 -256
- data/contrib/vagrant-softlayer-boxes +418 -416
- data/contrib/vagrant-softlayer-vlans +339 -329
- data/lib/vagrant-softlayer/action/create_instance.rb +74 -74
- data/lib/vagrant-softlayer/action/setup_softlayer.rb +39 -39
- data/lib/vagrant-softlayer/action/update_dns.rb +94 -94
- data/lib/vagrant-softlayer/action/wait_for_provision.rb +40 -40
- data/lib/vagrant-softlayer/action/wait_for_rebuild.rb +38 -36
- data/lib/vagrant-softlayer/config.rb +282 -268
- data/lib/vagrant-softlayer/util/load_balancer.rb +96 -103
- data/lib/vagrant-softlayer/util/network.rb +75 -75
- data/lib/vagrant-softlayer/util/warden.rb +38 -38
- data/lib/vagrant-softlayer/version.rb +5 -5
- data/spec/vagrant-softlayer/config_spec.rb +271 -267
- data/vagrant-softlayer.gemspec +55 -55
- metadata +4 -4
@@ -1,416 +1,418 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'getoptlong'
|
4
|
-
require 'tmpdir'
|
5
|
-
|
6
|
-
require 'rubygems'
|
7
|
-
require 'softlayer_api'
|
8
|
-
|
9
|
-
$sl = {
|
10
|
-
:data => {
|
11
|
-
:create_opts => nil,
|
12
|
-
:private_images => nil,
|
13
|
-
:public_images => nil
|
14
|
-
},
|
15
|
-
:service => {
|
16
|
-
:account => nil,
|
17
|
-
:virtual_guest => nil,
|
18
|
-
:virtual_guest_block_device_template_group => nil
|
19
|
-
},
|
20
|
-
:sl_credentials => {
|
21
|
-
:api_key => nil,
|
22
|
-
:endpoint_url => SoftLayer::API_PUBLIC_ENDPOINT,
|
23
|
-
:
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
:
|
31
|
-
|
32
|
-
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
:
|
42
|
-
:
|
43
|
-
:
|
44
|
-
:
|
45
|
-
:
|
46
|
-
:
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
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
|
-
|
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
|
-
$boxes[:dir][:
|
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
|
-
$boxes[:
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
if $sl[:sl_credentials][:
|
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
|
-
end
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
$sl[:service][:
|
261
|
-
|
262
|
-
$
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
$sl[:data][:
|
270
|
-
|
271
|
-
$
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
$boxes[:data][boxgroup].
|
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
|
-
end
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
$
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
end
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
$
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
fout.puts
|
348
|
-
|
349
|
-
|
350
|
-
fout.puts
|
351
|
-
|
352
|
-
fout.puts
|
353
|
-
fout.puts "#
|
354
|
-
fout.puts "#
|
355
|
-
fout.puts "#
|
356
|
-
|
357
|
-
fout.puts
|
358
|
-
|
359
|
-
fout.puts
|
360
|
-
|
361
|
-
fout.puts $boxes[:file_templates][:indent][
|
362
|
-
|
363
|
-
fout.puts $boxes[:file_templates][:indent][8] + "sl.
|
364
|
-
fout.puts $boxes[:file_templates][:indent][8] + "sl.
|
365
|
-
fout.puts $boxes[:file_templates][:indent][8] + "sl.
|
366
|
-
fout.puts $boxes[:file_templates][:indent][8] + "sl.
|
367
|
-
fout.puts $boxes[:file_templates][:indent][8] + "sl.
|
368
|
-
|
369
|
-
fout.puts $boxes[:file_templates][:indent][
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
end
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
end
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'getoptlong'
|
4
|
+
require 'tmpdir'
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'softlayer_api'
|
8
|
+
|
9
|
+
$sl = {
|
10
|
+
:data => {
|
11
|
+
:create_opts => nil,
|
12
|
+
:private_images => nil,
|
13
|
+
:public_images => nil
|
14
|
+
},
|
15
|
+
:service => {
|
16
|
+
:account => nil,
|
17
|
+
:virtual_guest => nil,
|
18
|
+
:virtual_guest_block_device_template_group => nil
|
19
|
+
},
|
20
|
+
:sl_credentials => {
|
21
|
+
:api_key => nil,
|
22
|
+
:endpoint_url => SoftLayer::API_PUBLIC_ENDPOINT,
|
23
|
+
:timeout => 60,
|
24
|
+
:user_agent => "vagrant-softlayer",
|
25
|
+
:username => nil
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
$boxes = {
|
30
|
+
:data => {},
|
31
|
+
:datacenter => nil,
|
32
|
+
:dir => {
|
33
|
+
:boxes => "boxes",
|
34
|
+
:vagrantfiles => "vagrantfiles",
|
35
|
+
:boxes_root => nil,
|
36
|
+
:output_root => File.expand_path("."),
|
37
|
+
:vagrantfiles_root => nil
|
38
|
+
},
|
39
|
+
:domain => nil,
|
40
|
+
:file_templates => {
|
41
|
+
:created_by => "# vagrant-softlayer-boxes automatic template export",
|
42
|
+
:end => "end",
|
43
|
+
:image_detail => "# Compute or flex image details:",
|
44
|
+
:indent => Hash.new() { |hash, key| hash[key] = " " * key },
|
45
|
+
:metadata_json => "{\"provider\": \"softlayer\"}",
|
46
|
+
:os_templates_avail => "# Available versions of this OS template (based on VM property selections):",
|
47
|
+
:sl_config_start => "config.vm.provider :softlayer do |sl|",
|
48
|
+
:vagrant_config_start => "Vagrant.configure(\"2\") do |config|"
|
49
|
+
},
|
50
|
+
:filter => nil,
|
51
|
+
:images => {
|
52
|
+
:private => true,
|
53
|
+
:public => true
|
54
|
+
},
|
55
|
+
:metadata_path => nil,
|
56
|
+
:monthly_billing => nil,
|
57
|
+
:templates => true,
|
58
|
+
:vlan_private => nil,
|
59
|
+
:vlan_public => nil
|
60
|
+
}
|
61
|
+
|
62
|
+
def procCliOptions()
|
63
|
+
opts = GetoptLong.new(
|
64
|
+
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
|
65
|
+
[ '--output_dir', '-o', GetoptLong::REQUIRED_ARGUMENT ],
|
66
|
+
[ '--only_images', '-i', GetoptLong::NO_ARGUMENT ],
|
67
|
+
[ '--only_private_images', '-p', GetoptLong::NO_ARGUMENT ],
|
68
|
+
[ '--only_public_images', '-g', GetoptLong::NO_ARGUMENT ],
|
69
|
+
[ '--only_templates', '-t', GetoptLong::NO_ARGUMENT ],
|
70
|
+
[ '--default_domain', GetoptLong::REQUIRED_ARGUMENT ],
|
71
|
+
[ '--default_datacenter', GetoptLong::REQUIRED_ARGUMENT ],
|
72
|
+
[ '--default_monthly_billing', GetoptLong::NO_ARGUMENT ],
|
73
|
+
[ '--default_vlan_private', GetoptLong::REQUIRED_ARGUMENT ],
|
74
|
+
[ '--default_vlan_public', GetoptLong::REQUIRED_ARGUMENT ],
|
75
|
+
[ '--sl_api_key', '-k', GetoptLong::REQUIRED_ARGUMENT ],
|
76
|
+
[ '--sl_endpoint_url', '-e', GetoptLong::REQUIRED_ARGUMENT ],
|
77
|
+
[ '--sl_username','-u', GetoptLong::REQUIRED_ARGUMENT ]
|
78
|
+
)
|
79
|
+
|
80
|
+
opts.each do | opt, optval |
|
81
|
+
case opt
|
82
|
+
when '--help'
|
83
|
+
puts <<-EOF
|
84
|
+
vagrant-softlayer-boxes [OPTION] [FILTER]
|
85
|
+
|
86
|
+
--help, -h:
|
87
|
+
Print this help.
|
88
|
+
|
89
|
+
--sl_username USERNAME, -u USERNAME:
|
90
|
+
Sets the SoftLayer account user name. If not specified, it is assumed SL_API_USERNAME environment variable is set.
|
91
|
+
|
92
|
+
--sl_api_key SL_API_KEY, -k SL_API_KEY:
|
93
|
+
Sets the SoftLayer API key. If not specified, it is assumed SL_API_KEY environment variable is set.
|
94
|
+
|
95
|
+
--sl_endpoint_url SL_API_BASE_URL, -e SL_API_BASE_URL:
|
96
|
+
Sets the SoftLayer endpoint URL. If not specified, it assumed SL_API_BASE_URL environment variable is set to API_PUBLIC_ENDPOINT or API_PRIVATE_ENDPOINT.
|
97
|
+
Defaults to API_PUBLIC_ENDPOINT.
|
98
|
+
|
99
|
+
--output_dir OUTPUTDIR, -o OUTPUTDIR:
|
100
|
+
Sets the root directory to create box output under.
|
101
|
+
|
102
|
+
--only_templates, -t:
|
103
|
+
Only create boxes for the CCI templates and not compute or flex images.
|
104
|
+
|
105
|
+
--only_images, -i:
|
106
|
+
Only create boxes for the compute or flex images and not the CCI templates.
|
107
|
+
|
108
|
+
--only_public_images, -g:
|
109
|
+
Only create boxes for the public compute or flex images and not the CCI templates.
|
110
|
+
|
111
|
+
--only_private_images, -p:
|
112
|
+
Only create boxes for the private compute or flex images and not the CCI templates.
|
113
|
+
|
114
|
+
--default_domain:
|
115
|
+
Set default vm domain.
|
116
|
+
|
117
|
+
--default_datacenter:
|
118
|
+
Set default vm datacenter.
|
119
|
+
|
120
|
+
--default_monthly_billing:
|
121
|
+
Set default billing type to monthly.
|
122
|
+
|
123
|
+
--default_vlan_private:
|
124
|
+
Set default vm private vlan.
|
125
|
+
|
126
|
+
--default_vlan_public:
|
127
|
+
Set default vm public vlan.
|
128
|
+
|
129
|
+
FILTER
|
130
|
+
String used to filter template and compute/flex images by name to export boxes for specific matches. Supports filtering by regular expression.
|
131
|
+
|
132
|
+
EOF
|
133
|
+
|
134
|
+
exit 0
|
135
|
+
|
136
|
+
when '--sl_username'
|
137
|
+
$sl[:sl_credentials][:username] = optval.to_s
|
138
|
+
|
139
|
+
when '--sl_api_key'
|
140
|
+
$sl[:sl_credentials][:api_key] = optval.to_s
|
141
|
+
|
142
|
+
when '--sl_endpoint_url'
|
143
|
+
if ! [ "API_PUBLIC_ENDPOINT", "API_PRIVATE_ENDPOINT" ].include?(optval.to_s.upcase)
|
144
|
+
$stderr.puts "ERROR: Invalid endpoint_url value: " + optval.to_s.upcase
|
145
|
+
exit 2
|
146
|
+
end
|
147
|
+
|
148
|
+
$sl[:sl_credentials][:endpoint_url] = (optval.to_s.upcase == 'API_PUBLIC_ENDPOINT' ? SoftLayer::API_PUBLIC_ENDPOINT : SoftLayer::API_PRIVATE_ENDPOINT )
|
149
|
+
|
150
|
+
when '--output_dir'
|
151
|
+
if File.exists?(optval.to_s) && File.ftype(optval.to_s) != 'directory'
|
152
|
+
$stderr.puts "ERROR: Path is not a directory: " + optval.to_s
|
153
|
+
exit 2
|
154
|
+
end
|
155
|
+
|
156
|
+
$boxes[:dir][:output_root] = File.expand_path(optval.to_s)
|
157
|
+
$boxes[:dir][:vagrantfiles_root] = File.join($boxes[:dir][:output_root], $boxes[:dir][:vagrantfiles])
|
158
|
+
$boxes[:dir][:boxes_root] = File.join($boxes[:dir][:output_root], $boxes[:dir][:boxes])
|
159
|
+
|
160
|
+
if File.exists?($boxes[:dir][:vagrantfiles_root]) && File.ftype($boxes[:dir][:vagrantfiles_root]) != 'directory'
|
161
|
+
$stderr.puts "ERROR: Output directory subdir is not a directory: " + $boxes[:dir][:vagrantfiles_root]
|
162
|
+
exit 2
|
163
|
+
end
|
164
|
+
|
165
|
+
if File.exists?($boxes[:dir][:boxes_root]) && File.ftype($boxes[:dir][:boxes_root]) != 'directory'
|
166
|
+
$stderr.puts "ERROR: Output directory subdir is not a directory: " + $boxes[:dir][:boxes_root]
|
167
|
+
exit 2
|
168
|
+
end
|
169
|
+
|
170
|
+
when '--only_templates'
|
171
|
+
$boxes[:images][:public] = false
|
172
|
+
$boxes[:images][:private] = false
|
173
|
+
|
174
|
+
when '--only_images'
|
175
|
+
$boxes[:templates] = false
|
176
|
+
|
177
|
+
when '--only_public_images'
|
178
|
+
$boxes[:templates] = false
|
179
|
+
$boxes[:images][:private] = false
|
180
|
+
|
181
|
+
when '--only_private_images'
|
182
|
+
$boxes[:templates] = false
|
183
|
+
$boxes[:images][:public] = false
|
184
|
+
|
185
|
+
when '--default_domain'
|
186
|
+
$boxes[:domain] = optval.to_s
|
187
|
+
|
188
|
+
when '--default_datacenter'
|
189
|
+
$boxes[:datacenter] = optval.to_s
|
190
|
+
|
191
|
+
when '--default_monthly_billing'
|
192
|
+
$boxes[:monthly_billing] = true
|
193
|
+
|
194
|
+
when '--default_vlan_private'
|
195
|
+
$boxes[:vlan_private] = optval.to_s
|
196
|
+
|
197
|
+
when'--default_vlan_public'
|
198
|
+
$boxes[:vlan_public] = optval.to_s
|
199
|
+
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
$boxes[:dir][:vagrantfiles_root] = File.join($boxes[:dir][:output_root], $boxes[:dir][:vagrantfiles])
|
204
|
+
$boxes[:dir][:boxes_root] = File.join($boxes[:dir][:output_root], $boxes[:dir][:boxes])
|
205
|
+
$boxes[:metadata_path] = File.join($boxes[:dir][:output_root], "metadata.json")
|
206
|
+
|
207
|
+
begin
|
208
|
+
[ $boxes[:dir][:output_root], $boxes[:dir][:vagrantfiles_root], $boxes[:dir][:boxes_root] ].each do |path|
|
209
|
+
Dir.mkdir(path, 0755) if ! File.exists?(path)
|
210
|
+
end
|
211
|
+
rescue Exception => e
|
212
|
+
$stderr.puts "ERROR: Failed to create output directories: " + e.message
|
213
|
+
exit 1
|
214
|
+
end
|
215
|
+
|
216
|
+
$sl[:sl_credentials][:username] = ENV["SL_API_USERNAME"] if $sl[:sl_credentials][:username].nil? && ENV.include?("SL_API_USERNAME")
|
217
|
+
$sl[:sl_credentials][:api_key] = ENV["SL_API_KEY"] if $sl[:sl_credentials][:api_key].nil? && ENV.include?("SL_API_KEY")
|
218
|
+
|
219
|
+
if $sl[:sl_credentials][:endpoint_url].nil? && ENV.include?("SL_API_BASE_URL")
|
220
|
+
if ! [ 'API_PRIVATE_ENDPOINT', 'API_PUBLIC_ENDPOINT' ].include?(ENV["SL_API_BASE_URL"])
|
221
|
+
$stderr.puts "ERROR: Invalid SoftLayer endpoint URL specified in environment variable SL_API_BASE_URL, expected one of #{[ 'API_PRIVATE_ENDPOINT', 'API_PUBLIC_ENDPOINT' ].inspect}: #{ENV["SL_API_BASE_URL"].inspect}"
|
222
|
+
exit 2
|
223
|
+
end
|
224
|
+
|
225
|
+
$sl[:sl_credentials][:endpoint_url] = (ENV["SL_API_BASE_URL"] == "API_PUBLIC_ENDPOINT" ? SoftLayer::API_PUBLIC_ENDPOINT : SoftLayer::API_PRIVATE_ENDPOINT )
|
226
|
+
end
|
227
|
+
|
228
|
+
if $sl[:sl_credentials][:username].nil?
|
229
|
+
$stderr.puts "ERROR: No SoftLayer username specified"
|
230
|
+
exit 2
|
231
|
+
end
|
232
|
+
|
233
|
+
if $sl[:sl_credentials][:username].nil?
|
234
|
+
$stderr.puts "ERROR: No SoftLayer user name specified"
|
235
|
+
exit 2
|
236
|
+
end
|
237
|
+
|
238
|
+
if $sl[:sl_credentials][:api_key].nil?
|
239
|
+
$stderr.puts "ERROR: No SoftLayer API key specified"
|
240
|
+
exit 2
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def procCliArgs()
|
245
|
+
if ARGV.length > 2
|
246
|
+
$stderr.puts "ERROR: Invalid argument supplied, please check help"
|
247
|
+
exit 2
|
248
|
+
elsif ARGV.length == 1
|
249
|
+
begin
|
250
|
+
$boxes[:filter] = Regexp.new(ARGV[0], Regexp::IGNORECASE)
|
251
|
+
rescue Exception => e
|
252
|
+
$stderr.puts "ERROR: Filter value is not a valid regular expression: " + e.message
|
253
|
+
exit 2
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def getBoxData()
|
259
|
+
begin
|
260
|
+
$sl[:service][:virtual_guest] = SoftLayer::Client.new($sl[:sl_credentials])["SoftLayer_Virtual_Guest"] if $boxes[:templates]
|
261
|
+
$sl[:service][:account] = SoftLayer::Client.new($sl[:sl_credentials])["SoftLayer_Account"] if $boxes[:images][:private]
|
262
|
+
$sl[:service][:virtual_guest_block_device_template_group] = SoftLayer::Client.new($sl[:sl_credentials])["SoftLayer_Virtual_Guest_Block_Device_Template_Group"] if $boxes[:images][:public]
|
263
|
+
rescue Exception => e
|
264
|
+
$stderr.puts "ERROR: Failed to create SoftLayer service object: " + e.message
|
265
|
+
exit 1
|
266
|
+
end
|
267
|
+
|
268
|
+
begin
|
269
|
+
$sl[:data][:create_opts] = $sl[:service][:virtual_guest].getCreateObjectOptions if $boxes[:templates]
|
270
|
+
$sl[:data][:private_images] = $sl[:service][:account].getBlockDeviceTemplateGroups.delete_if { |block_device| ! block_device.has_key?("globalIdentifier") } if $boxes[:images][:private]
|
271
|
+
$sl[:data][:public_images] = $sl[:service][:virtual_guest_block_device_template_group].getPublicImages.delete_if { |block_device| ! block_device.has_key?("globalIdentifier") } if $boxes[:images][:public]
|
272
|
+
rescue Exception => e
|
273
|
+
$stderr.puts "ERROR: Failed to retrieve SoftLayer service data: " + e.message
|
274
|
+
exit 1
|
275
|
+
end
|
276
|
+
|
277
|
+
if $boxes[:templates]
|
278
|
+
$sl[:data][:create_opts]["operatingSystems"].each do |os|
|
279
|
+
boxgroup = os["template"]["operatingSystemReferenceCode"].strip.gsub(/[()]/,'').gsub(/[^a-zA-Z0-9_.-]/, '_').upcase
|
280
|
+
|
281
|
+
#We dont want to allow separate instances for templates of same group name since the only difference is additional descriptions
|
282
|
+
if ! $boxes[:data].has_key?(boxgroup)
|
283
|
+
$boxes[:data][boxgroup] = Array.new()
|
284
|
+
|
285
|
+
$boxes[:data][boxgroup].push(
|
286
|
+
{
|
287
|
+
:type => :template,
|
288
|
+
:name => os["template"]["operatingSystemReferenceCode"],
|
289
|
+
:description => [ os["itemPrice"]["item"]["description"] ]
|
290
|
+
}
|
291
|
+
)
|
292
|
+
else
|
293
|
+
$boxes[:data][boxgroup][0][:description].push(os["itemPrice"]["item"]["description"])
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
$boxes[:images].each_key do |image_view|
|
299
|
+
if $boxes[:images][image_view]
|
300
|
+
$sl[:data][(image_view == :public ? :public_images : :private_images)].each do |image|
|
301
|
+
boxgroup = image["name"].strip.gsub(/[()]/,'').gsub(/[^a-zA-Z0-9_.-]/, '_').upcase
|
302
|
+
|
303
|
+
$boxes[:data][boxgroup] = Array.new() if ! $boxes[:data].has_key?(boxgroup)
|
304
|
+
$boxes[:data][boxgroup].push(
|
305
|
+
{
|
306
|
+
:type => :block_image,
|
307
|
+
:name => image["name"],
|
308
|
+
:global_id => image["globalIdentifier"],
|
309
|
+
:note => image["note"].to_s,
|
310
|
+
:summary => image["summary"].to_s,
|
311
|
+
:visibility => image_view
|
312
|
+
}
|
313
|
+
)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
def filterBoxes()
|
320
|
+
if ! $boxes[:filter].nil?
|
321
|
+
$boxes[:data].each_key do |boxgroup|
|
322
|
+
begin
|
323
|
+
$boxes[:data][boxgroup].delete_if { |box| ! box[:name].match($boxes[:filter]) }
|
324
|
+
rescue Exception => e
|
325
|
+
$stderr.puts "ERROR: Failed to filter Softlayer boxes: " + e.message
|
326
|
+
exit 1
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
def saveBoxFiles()
|
333
|
+
begin
|
334
|
+
File.open($boxes[:metadata_path], "w", 0644) { |fout| fout.puts $boxes[:file_templates][:metadata_json] }
|
335
|
+
rescue Exception => e
|
336
|
+
$stderr.puts "ERROR: Failed to save box metadata JSON data: " + e.message
|
337
|
+
exit 1
|
338
|
+
end
|
339
|
+
|
340
|
+
$boxes[:data].each_key do |boxgroup|
|
341
|
+
$boxes[:data][boxgroup].each do |box|
|
342
|
+
boxFileName = ($boxes[:data][boxgroup].length > 1 ? boxgroup + "_" + ($boxes[:data][boxgroup].index(box) + 1).to_s : boxgroup)
|
343
|
+
|
344
|
+
begin
|
345
|
+
File.open(File.join($boxes[:dir][:vagrantfiles_root], boxFileName + ".vagrantfile"), "w", 0644) do |fout|
|
346
|
+
fout.puts $boxes[:file_templates][:created_by]
|
347
|
+
fout.puts
|
348
|
+
|
349
|
+
fout.puts $boxes[:file_templates][:os_templates_avail] if box[:type] == :template
|
350
|
+
fout.puts box[:description].map { |descr| "# " + descr }.join("\n") if box[:type] == :template
|
351
|
+
|
352
|
+
fout.puts $boxes[:file_templates][:image_detail] if box[:type] == :block_image
|
353
|
+
fout.puts "# Global Identifier: " + box[:global_id].to_s if box[:type] == :block_image
|
354
|
+
fout.puts "# Name: " + box[:name] if box[:type] == :block_image
|
355
|
+
fout.puts "# Summary: " + box[:summary].to_s if box[:type] == :block_image
|
356
|
+
fout.puts "# Note: " + box[:note].to_s if box[:type] == :block_image
|
357
|
+
fout.puts "# Visibility: " + (box[:visibility] == :public ? "public" : "private" ) if box[:type] == :block_image
|
358
|
+
|
359
|
+
fout.puts
|
360
|
+
fout.puts $boxes[:file_templates][:vagrant_config_start]
|
361
|
+
fout.puts $boxes[:file_templates][:indent][4] + $boxes[:file_templates][:sl_config_start]
|
362
|
+
|
363
|
+
fout.puts $boxes[:file_templates][:indent][8] + "sl.datacenter = \"" + $boxes[:datacenter] + "\"" if $boxes[:datacenter]
|
364
|
+
fout.puts $boxes[:file_templates][:indent][8] + "sl.domain = \"" + $boxes[:domain] + "\"" if $boxes[:domain]
|
365
|
+
fout.puts $boxes[:file_templates][:indent][8] + "sl.hourly_billing = false" if $boxes[:monthly_billing]
|
366
|
+
fout.puts $boxes[:file_templates][:indent][8] + "sl.operating_system = \"" + box[:name] + "\"" if box[:type] == :template
|
367
|
+
fout.puts $boxes[:file_templates][:indent][8] + "sl.image_guid = \"" + box[:global_id].to_s + "\"" if box[:type] == :block_image
|
368
|
+
fout.puts $boxes[:file_templates][:indent][8] + "sl.vlan_private = \"" + $boxes[:vlan_private] + "\"" if $boxes[:vlan_private]
|
369
|
+
fout.puts $boxes[:file_templates][:indent][8] + "sl.vlan_public = \"" + $boxes[:vlan_public] + "\"" if $boxes[:vlan_public]
|
370
|
+
|
371
|
+
fout.puts $boxes[:file_templates][:indent][4] + $boxes[:file_templates][:end]
|
372
|
+
fout.puts $boxes[:file_templates][:end]
|
373
|
+
end
|
374
|
+
rescue Exception => e
|
375
|
+
$stderr.puts "ERROR: Failed to save box Vagrantfile: " + e.message
|
376
|
+
exit 1
|
377
|
+
end
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
def createBoxes()
|
383
|
+
$boxes[:data].each_key do |boxgroup|
|
384
|
+
$boxes[:data][boxgroup].each do |box|
|
385
|
+
boxFileName = ($boxes[:data][boxgroup].length > 1 ? boxgroup + "_" + ($boxes[:data][boxgroup].index(box) + 1).to_s : boxgroup)
|
386
|
+
|
387
|
+
begin
|
388
|
+
Dir.mktmpdir do |tmpDir|
|
389
|
+
FileUtils.cd(tmpDir) do
|
390
|
+
FileUtils.cp($boxes[:metadata_path], File.join(tmpDir,"metadata.json"), :preserve => true)
|
391
|
+
FileUtils.cp(File.join($boxes[:dir][:vagrantfiles_root], boxFileName + ".vagrantfile"), File.join(tmpDir, "Vagrantfile"), :preserve => true)
|
392
|
+
|
393
|
+
result = %x(tar -czvf "#{File.join($boxes[:dir][:boxes_root], boxFileName + ".box.tar.gz")}" Vagrantfile metadata.json)
|
394
|
+
|
395
|
+
raise result if $?.exitstatus != 0
|
396
|
+
|
397
|
+
FileUtils.mv(File.join($boxes[:dir][:boxes_root], boxFileName + ".box.tar.gz"), File.join($boxes[:dir][:boxes_root], boxFileName + ".box"), :force => true)
|
398
|
+
FileUtils.chmod(0644, File.join($boxes[:dir][:boxes_root], boxFileName + ".box"))
|
399
|
+
end
|
400
|
+
end
|
401
|
+
rescue Exception => e
|
402
|
+
$stderr.puts "ERROR: Failed to save Vagrant box: " + e.message
|
403
|
+
exit 1
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
def main()
|
410
|
+
procCliOptions()
|
411
|
+
procCliArgs()
|
412
|
+
getBoxData()
|
413
|
+
filterBoxes()
|
414
|
+
saveBoxFiles()
|
415
|
+
createBoxes()
|
416
|
+
end
|
417
|
+
|
418
|
+
main
|