vagrant-softlayer 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -24
  3. data/QUICKSTART.md +377 -0
  4. data/README.md +25 -20
  5. data/contrib/README.md +8 -1
  6. data/contrib/vagrant-softlayer-boxes +416 -408
  7. data/contrib/vagrant-softlayer-vlans +329 -0
  8. data/contrib/vagrantcloud/CENTOS_5_32.box +0 -0
  9. data/contrib/vagrantcloud/CENTOS_5_64.box +0 -0
  10. data/contrib/vagrantcloud/CENTOS_6_32.box +0 -0
  11. data/contrib/vagrantcloud/CENTOS_6_64.box +0 -0
  12. data/contrib/vagrantcloud/CENTOS_LATEST.box +0 -0
  13. data/contrib/vagrantcloud/CENTOS_LATEST_32.box +0 -0
  14. data/contrib/vagrantcloud/CENTOS_LATEST_64.box +0 -0
  15. data/contrib/vagrantcloud/CLOUDLINUX_5_32.box +0 -0
  16. data/contrib/vagrantcloud/CLOUDLINUX_5_64.box +0 -0
  17. data/contrib/vagrantcloud/CLOUDLINUX_6_32.box +0 -0
  18. data/contrib/vagrantcloud/CLOUDLINUX_6_64.box +0 -0
  19. data/contrib/vagrantcloud/CLOUDLINUX_LATEST.box +0 -0
  20. data/contrib/vagrantcloud/CLOUDLINUX_LATEST_32.box +0 -0
  21. data/contrib/vagrantcloud/CLOUDLINUX_LATEST_64.box +0 -0
  22. data/contrib/vagrantcloud/DEBIAN_5_32.box +0 -0
  23. data/contrib/vagrantcloud/DEBIAN_5_64.box +0 -0
  24. data/contrib/vagrantcloud/DEBIAN_6_32.box +0 -0
  25. data/contrib/vagrantcloud/DEBIAN_6_64.box +0 -0
  26. data/contrib/vagrantcloud/DEBIAN_7_32.box +0 -0
  27. data/contrib/vagrantcloud/DEBIAN_7_64.box +0 -0
  28. data/contrib/vagrantcloud/DEBIAN_LATEST.box +0 -0
  29. data/contrib/vagrantcloud/DEBIAN_LATEST_32.box +0 -0
  30. data/contrib/vagrantcloud/DEBIAN_LATEST_64.box +0 -0
  31. data/contrib/vagrantcloud/REDHAT_5_32.box +0 -0
  32. data/contrib/vagrantcloud/REDHAT_5_64.box +0 -0
  33. data/contrib/vagrantcloud/REDHAT_6_32.box +0 -0
  34. data/contrib/vagrantcloud/REDHAT_6_64.box +0 -0
  35. data/contrib/vagrantcloud/REDHAT_LATEST.box +0 -0
  36. data/contrib/vagrantcloud/REDHAT_LATEST_32.box +0 -0
  37. data/contrib/vagrantcloud/REDHAT_LATEST_64.box +0 -0
  38. data/contrib/vagrantcloud/SL_GENERIC.box +0 -0
  39. data/contrib/vagrantcloud/UBUNTU_10_32.box +0 -0
  40. data/contrib/vagrantcloud/UBUNTU_10_64.box +0 -0
  41. data/contrib/vagrantcloud/UBUNTU_12_32.box +0 -0
  42. data/contrib/vagrantcloud/UBUNTU_12_64.box +0 -0
  43. data/contrib/vagrantcloud/UBUNTU_14_32.box +0 -0
  44. data/contrib/vagrantcloud/UBUNTU_14_64.box +0 -0
  45. data/contrib/vagrantcloud/UBUNTU_8_32.box +0 -0
  46. data/contrib/vagrantcloud/UBUNTU_8_64.box +0 -0
  47. data/contrib/vagrantcloud/UBUNTU_LATEST.box +0 -0
  48. data/contrib/vagrantcloud/UBUNTU_LATEST_32.box +0 -0
  49. data/contrib/vagrantcloud/UBUNTU_LATEST_64.box +0 -0
  50. data/contrib/vagrantcloud/VYATTACE_6.5_64.box +0 -0
  51. data/contrib/vagrantcloud/VYATTACE_6.6_64.box +0 -0
  52. data/contrib/vagrantcloud/VYATTACE_LATEST.box +0 -0
  53. data/contrib/vagrantcloud/VYATTACE_LATEST_64.box +0 -0
  54. data/contrib/vagrantcloud/WIN_2003-DC-SP2-1_32.box +0 -0
  55. data/contrib/vagrantcloud/WIN_2003-DC-SP2-1_64.box +0 -0
  56. data/contrib/vagrantcloud/WIN_2003-ENT-SP2-5_32.box +0 -0
  57. data/contrib/vagrantcloud/WIN_2003-ENT-SP2-5_64.box +0 -0
  58. data/contrib/vagrantcloud/WIN_2003-STD-SP2-5_32.box +0 -0
  59. data/contrib/vagrantcloud/WIN_2003-STD-SP2-5_64.box +0 -0
  60. data/contrib/vagrantcloud/WIN_2008-DC-R2_64.box +0 -0
  61. data/contrib/vagrantcloud/WIN_2008-DC-SP2_32.box +0 -0
  62. data/contrib/vagrantcloud/WIN_2008-DC-SP2_64.box +0 -0
  63. data/contrib/vagrantcloud/WIN_2008-ENT-R2_64.box +0 -0
  64. data/contrib/vagrantcloud/WIN_2008-ENT-SP2_32.box +0 -0
  65. data/contrib/vagrantcloud/WIN_2008-ENT-SP2_64.box +0 -0
  66. data/contrib/vagrantcloud/WIN_2008-STD-R2-SP1_64.box +0 -0
  67. data/contrib/vagrantcloud/WIN_2008-STD-R2_64.box +0 -0
  68. data/contrib/vagrantcloud/WIN_2008-STD-SP2_32.box +0 -0
  69. data/contrib/vagrantcloud/WIN_2008-STD-SP2_64.box +0 -0
  70. data/contrib/vagrantcloud/WIN_2012-DC_64.box +0 -0
  71. data/contrib/vagrantcloud/WIN_2012-STD_64.box +0 -0
  72. data/contrib/vagrantcloud/WIN_LATEST.box +0 -0
  73. data/contrib/vagrantcloud/WIN_LATEST_32.box +0 -0
  74. data/contrib/vagrantcloud/WIN_LATEST_64.box +0 -0
  75. data/lib/vagrant-softlayer/action.rb +20 -16
  76. data/lib/vagrant-softlayer/action/create_instance.rb +24 -8
  77. data/lib/vagrant-softlayer/action/setup_softlayer.rb +2 -1
  78. data/lib/vagrant-softlayer/action/sync_folders.rb +99 -99
  79. data/lib/vagrant-softlayer/action/wait_for_rebuild.rb +36 -36
  80. data/lib/vagrant-softlayer/config.rb +10 -2
  81. data/lib/vagrant-softlayer/errors.rb +33 -29
  82. data/lib/vagrant-softlayer/plugin.rb +77 -77
  83. data/lib/vagrant-softlayer/util/load_balancer.rb +103 -103
  84. data/lib/vagrant-softlayer/util/network.rb +75 -73
  85. data/lib/vagrant-softlayer/util/warden.rb +38 -38
  86. data/lib/vagrant-softlayer/version.rb +5 -5
  87. data/locales/en.yml +6 -0
  88. data/spec/vagrant-softlayer/config_spec.rb +4 -2
  89. data/vagrant-softlayer.gemspec +55 -55
  90. metadata +71 -2
data/README.md CHANGED
@@ -79,26 +79,27 @@ See [Join load balancers](https://github.com/audiolize/vagrant-softlayer/wiki/Jo
79
79
 
80
80
  ### Instance Configuration
81
81
 
82
- Parameter | Description | Default | Required
83
- ------------------ | ---------------------------------------------------------- | ----------------------- | --------
84
- `datacenter` | Datacenter shortname | First available | no
85
- `dedicated` | Allocate a dedicated CCI (non-shared host) | false | no
86
- `disk_capacity` | The capacity of each disk | | no **
87
- `domain` | The domain of the instance | | yes
88
- `hostname` | The hostname of the instance | | yes *
89
- `hourly_billing` | Hourly billing type (false for monthly) | true | no
90
- `image_guid` | The global identifier for the compute or flex image to use | | no **
91
- `local_disk` | Use a local disk (false for SAN) | true | no
92
- `max_memory` | The amount of RAM of the instance in Mb | 1024 | no
93
- `network_speed` | Network port speed in Mbps | 10 | no
94
- `operating_system` | The instance operating system identifier | UBUNTU_LATEST | no **
95
- `post_install` | URI of Post-install script to download | | no
96
- `private_only` | Only create access to the private network | false | no
97
- `ssh_key` | ID or label of the SSH key(s) to provision | | yes
98
- `start_cpus` | The number of processors of the instance | 1 | no
99
- `user_data` | User defined metadata string | | no
100
- `vlan_private` | The ID of the private VLAN | Automatically generated | no
101
- `vlan_public` | The ID of the public VLAN | Automatically generated | no
82
+ Parameter | Description | Default | Required
83
+ ------------------ | -----------------------------------------------------------| ----------------| --------
84
+ `datacenter` | Datacenter shortname | First available | no
85
+ `dedicated` | Allocate a dedicated CCI (non-shared host) | false | no
86
+ `disk_capacity` | The capacity of each disk | | no **
87
+ `domain` | The domain of the instance | | yes
88
+ `force_private_ip` | Use private IP for communication even if public IP is set | false | no
89
+ `hostname` | The hostname of the instance | | yes *
90
+ `hourly_billing` | Hourly billing type (false for monthly) | true | no
91
+ `image_guid` | The global identifier for the compute or flex image to use | | no **
92
+ `local_disk` | Use a local disk (false for SAN) | true | no
93
+ `max_memory` | The amount of RAM of the instance in Mb | 1024 | no
94
+ `network_speed` | Network port speed in Mbps | 10 | no
95
+ `operating_system` | The instance operating system identifier | UBUNTU_LATEST | no **
96
+ `post_install` | URI of Post-install script to download | | no
97
+ `private_only` | Only create access to the private network | false | no
98
+ `ssh_key` | ID or label of the SSH key(s) to provision | | yes
99
+ `start_cpus` | The number of processors of the instance | 1 | no
100
+ `user_data` | User defined metadata string | | no
101
+ `vlan_private` | The ID, name or qualified name of the private VLAN | Auto-generated | no
102
+ `vlan_public` | The ID, name or qualified name of the public VLAN | Auto-generated | no
102
103
 
103
104
  \* The `hostname` could be specified either using `config.vm.hostname` or the provider parameter.
104
105
 
@@ -208,6 +209,10 @@ Also, a bunch of aliases for the `ssh_key` parameter are provided for better sem
208
209
  * `ssh_key_name`
209
210
  * `ssh_key_names`
210
211
 
212
+ ## Quick Start Guide
213
+
214
+ For those new to Vagrant, see the [Quick Start Guide](https://github.com/audiolize/vagrant-softlayer/blob/master/QUICKSTART.md).
215
+
211
216
  ## Development
212
217
 
213
218
  To work on the `vagrant-softlayer` plugin, clone this repository out, and use
data/contrib/README.md CHANGED
@@ -6,6 +6,13 @@ for each item will be kept below.
6
6
 
7
7
  ## List of Contrib Items
8
8
 
9
+ * `vagrantcloud` - Vagrant boxes used by Vagrant Cloud examples in the Quick Start
10
+ guide or for manual install locally without having to use `vagrant-softlayer-boxes`.
9
11
  * `vagrant-softlayer-boxes` - Vagrant box creation tool which allows you to create
10
12
  starter boxes from those offered in the SoftLayer API or from public/private compute
11
- or flex images associated with your SoftLayer account.
13
+ or flex images associated with your SoftLayer account.
14
+ * `vagrant-softlayer-vlans` - SoftLayer vlan tool which allows you to list the data
15
+ for all SoftLayer vlans associated with your account that are usable for assigning to
16
+ CCI's during `vagrant-softlayer` provisioning. It provides the id, name, and qualified
17
+ name of vlans that can be used with the `vlan_private` and `vlan_public`
18
+ `vagrant-softlayer` settings.
@@ -1,408 +1,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
- :username => nil
24
- }
25
- }
26
-
27
- $boxes = {
28
- :data => {},
29
- :datacenter => nil,
30
- :dir => {
31
- :boxes => "boxes",
32
- :vagrantfiles => "vagrantfiles",
33
- :boxes_root => nil,
34
- :output_root => File.expand_path("."),
35
- :vagrantfiles_root => nil
36
- },
37
- :domain => nil,
38
- :file_templates => {
39
- :created_by => "# vagrant-softlayer-boxes automatic template export",
40
- :end => "end",
41
- :image_detail => "# Compute or flex image details:",
42
- :indent => Hash.new() { |hash, key| hash[key] = " " * key },
43
- :metadata_json => "{\"provider\": \"softlayer\"}",
44
- :os_templates_avail => "# Available versions of this OS template (based on VM property selections):",
45
- :sl_config_start => "config.vm.provider :softlayer do |sl|",
46
- :vagrant_config_start => "Vagrant.configure(\"2\") do |config|"
47
- },
48
- :filter => nil,
49
- :images => {
50
- :private => true,
51
- :public => true
52
- },
53
- :metadata_path => nil,
54
- :monthly_billing => nil,
55
- :templates => true,
56
- :vlan_private => nil,
57
- :vlan_public => nil
58
- }
59
-
60
- def procCliOptions()
61
- opts = GetoptLong.new(
62
- [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
63
- [ '--output_dir', '-o', GetoptLong::REQUIRED_ARGUMENT ],
64
- [ '--only_images', '-i', GetoptLong::NO_ARGUMENT ],
65
- [ '--only_private_images', '-p', GetoptLong::NO_ARGUMENT ],
66
- [ '--only_public_images', '-g', GetoptLong::NO_ARGUMENT ],
67
- [ '--only_templates', '-t', GetoptLong::NO_ARGUMENT ],
68
- [ '--default_domain', GetoptLong::REQUIRED_ARGUMENT ],
69
- [ '--default_datacenter', GetoptLong::REQUIRED_ARGUMENT ],
70
- [ '--default_monthly_billing', GetoptLong::NO_ARGUMENT ],
71
- [ '--default_vlan_private', GetoptLong::REQUIRED_ARGUMENT ],
72
- [ '--default_vlan_public', GetoptLong::REQUIRED_ARGUMENT ],
73
- [ '--sl_api_key', '-k', GetoptLong::REQUIRED_ARGUMENT ],
74
- [ '--sl_endpoint_url', '-e', GetoptLong::REQUIRED_ARGUMENT ],
75
- [ '--sl_username','-u', GetoptLong::REQUIRED_ARGUMENT ]
76
- )
77
-
78
- opts.each do | opt, optval |
79
- case opt
80
- when '--help'
81
- puts <<-EOF
82
- vagrant-softlayer-boxes [OPTION] [FILTER]
83
-
84
- --help, -h:
85
- Print this help.
86
-
87
- --sl_username USERNAME, -u USERNAME:
88
- Sets the SoftLayer account user name. If not specified, it is assumed SL_API_USERNAME environment variable is set.
89
-
90
- --sl_api_key SL_API_KEY, -k SL_API_KEY:
91
- Sets the SoftLayer API key. If not specified, it is assumed SL_API_KEY environment variable is set.
92
-
93
- --sl_endpoint_url SL_API_BASE_URL, -e SL_API_BASE_URL:
94
- 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.
95
- Defaults to API_PUBLIC_ENDPOINT.
96
-
97
- --output_dir OUTPUTDIR, -o OUTPUTDIR:
98
- Sets the root directory to create box output under.
99
-
100
- --only_templates, -t:
101
- Only create boxes for the CCI templates and not compute or flex images.
102
-
103
- --only_images, -i:
104
- Only create boxes for the compute or flex images and not the CCI templates.
105
-
106
- --only_public_images, -g:
107
- Only create boxes for the public compute or flex images and not the CCI templates.
108
-
109
- --only_private_images, -p:
110
- Only create boxes for the private compute or flex images and not the CCI templates.
111
-
112
- --default_domain:
113
- Set default vm domain.
114
-
115
- --default_datacenter:
116
- Set default vm datacenter.
117
-
118
- --default_monthly_billing:
119
- Set default billing type to monthly.
120
-
121
- --default_vlan_private:
122
- Set default vm private vlan.
123
-
124
- --default_vlan_public:
125
- Set default vm public vlan.
126
-
127
- FILTER
128
- String used to filter template and compute/flex images by name to export boxes for specific matches. Supports filtering by regular expression.
129
-
130
- EOF
131
-
132
- exit 0
133
-
134
- when '--sl_username'
135
- $sl[:sl_credentials][:username] = optval.to_s
136
-
137
- when '--sl_api_key'
138
- $sl[:sl_credentials][:api_key] = optval.to_s
139
-
140
- when '--sl_endpoint_url'
141
- if ! [ "API_PUBLIC_ENDPOINT", "API_PRIVATE_ENDPOINT" ].include?(optval.to_s.upcase)
142
- $stderr.puts "ERROR: Invalid endpoint_url value: " + optval.to_s.upcase
143
- exit 2
144
- end
145
-
146
- $sl[:sl_credentials][:endpoint_url] = (optval.to_s.upcase == 'API_PUBLIC_ENDPOINT' ? SoftLayer::API_PUBLIC_ENDPOINT : SoftLayer::API_PRIVATE_ENDPOINT )
147
-
148
- when '--output_dir'
149
- if File.exists?(optval.to_s) && File.ftype(optval.to_s) != 'directory'
150
- $stderr.puts "ERROR: Path is not a directory: " + optval.to_s
151
- exit 2
152
- end
153
-
154
- $boxes[:dir][:output_root] = File.expand_path(optval.to_s)
155
- $boxes[:dir][:vagrantfiles_root] = File.join($boxes[:dir][:output_root], $boxes[:dir][:vagrantfiles])
156
- $boxes[:dir][:boxes_root] = File.join($boxes[:dir][:output_root], $boxes[:dir][:boxes])
157
-
158
- if File.exists?($boxes[:dir][:vagrantfiles_root]) && File.ftype($boxes[:dir][:vagrantfiles_root]) != 'directory'
159
- $stderr.puts "ERROR: Output directory subdir is not a directory: " + $boxes[:dir][:vagrantfiles_root]
160
- exit 2
161
- end
162
-
163
- if File.exists?($boxes[:dir][:boxes_root]) && File.ftype($boxes[:dir][:boxes_root]) != 'directory'
164
- $stderr.puts "ERROR: Output directory subdir is not a directory: " + $boxes[:dir][:boxes_root]
165
- exit 2
166
- end
167
-
168
- when '--only_templates'
169
- $boxes[:images][:public] = false
170
- $boxes[:images][:private] = false
171
-
172
- when '--only_images'
173
- $boxes[:templates] = false
174
-
175
- when '--only_public_images'
176
- $boxes[:templates] = false
177
- $boxes[:images][:private] = false
178
-
179
- when '--only_private_images'
180
- $boxes[:templates] = false
181
- $boxes[:images][:public] = false
182
-
183
- when '--default_domain'
184
- $boxes[:domain] = optval.to_s
185
-
186
- when '--default_datacenter'
187
- $boxes[:datacenter] = optval.to_s
188
-
189
- when '--default_monthly_billing'
190
- $boxes[:monthly_billing] = true
191
-
192
- when '--default_vlan_private'
193
- $boxes[:vlan_private] = optval.to_s
194
-
195
- when'--default_vlan_public'
196
- $boxes[:vlan_public] = optval.to_s
197
-
198
- end
199
- end
200
-
201
- $boxes[:dir][:vagrantfiles_root] = File.join($boxes[:dir][:output_root], $boxes[:dir][:vagrantfiles])
202
- $boxes[:dir][:boxes_root] = File.join($boxes[:dir][:output_root], $boxes[:dir][:boxes])
203
- $boxes[:metadata_path] = File.join($boxes[:dir][:output_root], "metadata.json")
204
-
205
- begin
206
- [ $boxes[:dir][:output_root], $boxes[:dir][:vagrantfiles_root], $boxes[:dir][:boxes_root] ].each do |path|
207
- Dir.mkdir(path, 0755) if ! File.exists?(path)
208
- end
209
- rescue Exception => e
210
- $stderr.puts "ERROR: Failed to create output directories: " + e.message
211
- exit 1
212
- end
213
-
214
- $sl[:sl_credentials][:username] = ENV["SL_API_USERNAME"] if $sl[:sl_credentials][:username].nil? && ENV.include?("SL_API_USERNAME")
215
- $sl[:sl_credentials][:api_key] = ENV["SL_API_KEY"] if $sl[:sl_credentials][:api_key].nil? && ENV.include?("SL_API_KEY")
216
- $sl[:sl_credentials][:endpoint_url] = (ENV["SL_API_BASE_URL"] == "API_PUBLIC_ENDPOINT" ? SoftLayer::API_PUBLIC_ENDPOINT : SoftLayer::API_PRIVATE_ENDPOINT ) if $sl[:sl_credentials][:endpoint_url].nil? && ENV.include?("SL_API_BASE_URL")
217
-
218
- if $sl[:sl_credentials][:username].nil?
219
- $stderr.puts "ERROR: No SoftLayer username specified"
220
- exit 2
221
- end
222
-
223
- if $sl[:sl_credentials][:username].nil?
224
- $stderr.puts "ERROR: No SoftLayer user name specified"
225
- exit 2
226
- end
227
-
228
- if $sl[:sl_credentials][:api_key].nil?
229
- $stderr.puts "ERROR: No SoftLayer API key specified"
230
- exit 2
231
- end
232
- end
233
-
234
- def procCliArgs()
235
- if ARGV.length > 2
236
- $stderr.puts "ERROR: Invalid argument supplied, please check help"
237
- exit 2
238
- elsif ARGV.length == 1
239
- begin
240
- $boxes[:filter] = Regexp.new(ARGV[0], Regexp::IGNORECASE)
241
- rescue Exception => e
242
- $stderr.puts "ERROR: Filter value is not a valid regular expression: " + e.message
243
- exit 2
244
- end
245
- end
246
- end
247
-
248
- def getBoxData()
249
- begin
250
- $sl[:service][:virtual_guest] = SoftLayer::Service.new("SoftLayer_Virtual_Guest", $sl[:sl_credentials]) if $boxes[:templates]
251
- $sl[:service][:account] = SoftLayer::Service.new("SoftLayer_Account", $sl[:sl_credentials]) if $boxes[:images][:private]
252
- $sl[:service][:virtual_guest_block_device_template_group] = SoftLayer::Service.new("SoftLayer_Virtual_Guest_Block_Device_Template_Group", $sl[:sl_credentials]) if $boxes[:images][:public]
253
- rescue Exception => e
254
- $stderr.puts "ERROR: Failed to create SoftLayer service object: " + e.message
255
- exit 1
256
- end
257
-
258
- begin
259
- $sl[:data][:create_opts] = $sl[:service][:virtual_guest].getCreateObjectOptions if $boxes[:templates]
260
- $sl[:data][:private_images] = $sl[:service][:account].getBlockDeviceTemplateGroups.delete_if { |block_device| ! block_device.has_key?("globalIdentifier") } if $boxes[:images][:private]
261
- $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]
262
- rescue Exception => e
263
- $stderr.puts "ERROR: Failed to retrieve SoftLayer service data: " + e.message
264
- exit 1
265
- end
266
-
267
- if $boxes[:templates]
268
- $sl[:data][:create_opts]["operatingSystems"].each do |os|
269
- boxgroup = os["template"]["operatingSystemReferenceCode"].strip.gsub(/[()]/,'').gsub(/[^a-zA-Z0-9_.-]/, '_').upcase
270
-
271
- #We dont want to allow separate instances for templates of same group name since the only difference is additional descriptions
272
- if ! $boxes[:data].has_key?(boxgroup)
273
- $boxes[:data][boxgroup] = Array.new()
274
-
275
- $boxes[:data][boxgroup].push(
276
- {
277
- :type => :template,
278
- :name => os["template"]["operatingSystemReferenceCode"],
279
- :description => [ os["itemPrice"]["item"]["description"] ]
280
- }
281
- )
282
- else
283
- $boxes[:data][boxgroup][0][:description].push(os["itemPrice"]["item"]["description"])
284
- end
285
- end
286
- end
287
-
288
- $boxes[:images].each_key do |image_view|
289
- if $boxes[:images][image_view]
290
- $sl[:data][(image_view == :public ? :public_images : :private_images)].each do |image|
291
- boxgroup = image["name"].strip.gsub(/[()]/,'').gsub(/[^a-zA-Z0-9_.-]/, '_').upcase
292
-
293
- $boxes[:data][boxgroup] = Array.new() if ! $boxes[:data].has_key?(boxgroup)
294
- $boxes[:data][boxgroup].push(
295
- {
296
- :type => :block_image,
297
- :name => image["name"],
298
- :global_id => image["globalIdentifier"],
299
- :note => image["note"].to_s,
300
- :summary => image["summary"].to_s,
301
- :visibility => image_view
302
- }
303
- )
304
- end
305
- end
306
- end
307
- end
308
-
309
- def filterBoxes()
310
- if ! $boxes[:filter].nil?
311
- $boxes[:data].each_key do |boxgroup|
312
- begin
313
- $boxes[:data][boxgroup].delete_if { |box| ! box[:name].match($boxes[:filter]) }
314
- rescue Exception => e
315
- $stderr.puts "ERROR: Failed to filter Softlayer boxes: " + e.message
316
- exit 1
317
- end
318
- end
319
- end
320
- end
321
-
322
- def saveBoxFiles()
323
- begin
324
- File.open($boxes[:metadata_path], "w", 0644) { |fout| fout.puts $boxes[:file_templates][:metadata_json] }
325
- rescue Exception => e
326
- $stderr.puts "ERROR: Failed to save box metadata JSON data: " + e.message
327
- exit 1
328
- end
329
-
330
- $boxes[:data].each_key do |boxgroup|
331
- $boxes[:data][boxgroup].each do |box|
332
- boxFileName = ($boxes[:data][boxgroup].length > 1 ? boxgroup + "_" + ($boxes[:data][boxgroup].index(box) + 1).to_s : boxgroup)
333
-
334
- begin
335
- File.open(File.join($boxes[:dir][:vagrantfiles_root], boxFileName + ".vagrantfile"), "w", 0644) do |fout|
336
- fout.puts $boxes[:file_templates][:created_by]
337
- fout.puts
338
-
339
- fout.puts $boxes[:file_templates][:os_templates_avail] if box[:type] == :template
340
- fout.puts box[:description].map { |descr| "# " + descr }.join("\n") if box[:type] == :template
341
-
342
- fout.puts $boxes[:file_templates][:image_detail] if box[:type] == :block_image
343
- fout.puts "# Global Identifier: " + box[:global_id].to_s if box[:type] == :block_image
344
- fout.puts "# Name: " + box[:name] if box[:type] == :block_image
345
- fout.puts "# Summary: " + box[:summary].to_s if box[:type] == :block_image
346
- fout.puts "# Note: " + box[:note].to_s if box[:type] == :block_image
347
- fout.puts "# Visibility: " + (box[:visibility] == :public ? "public" : "private" ) if box[:type] == :block_image
348
-
349
- fout.puts
350
- fout.puts $boxes[:file_templates][:vagrant_config_start]
351
- fout.puts $boxes[:file_templates][:indent][4] + $boxes[:file_templates][:sl_config_start]
352
-
353
- fout.puts $boxes[:file_templates][:indent][8] + "sl.datacenter = \"" + $boxes[:datacenter] + "\"" if $boxes[:datacenter]
354
- fout.puts $boxes[:file_templates][:indent][8] + "sl.domain = \"" + $boxes[:domain] + "\"" if $boxes[:domain]
355
- fout.puts $boxes[:file_templates][:indent][8] + "sl.hourly_billing = false" if $boxes[:monthly_billing]
356
- fout.puts $boxes[:file_templates][:indent][8] + "sl.operating_system = \"" + box[:name] + "\"" if box[:type] == :template
357
- fout.puts $boxes[:file_templates][:indent][8] + "sl.image_guid = \"" + box[:global_id].to_s + "\"" if box[:type] == :block_image
358
- fout.puts $boxes[:file_templates][:indent][8] + "sl.vlan_private = \"" + $boxes[:vlan_private] + "\"" if $boxes[:vlan_private]
359
- fout.puts $boxes[:file_templates][:indent][8] + "sl.vlan_public = \"" + $boxes[:vlan_public] + "\"" if $boxes[:vlan_public]
360
-
361
- fout.puts $boxes[:file_templates][:indent][4] + $boxes[:file_templates][:end]
362
- fout.puts $boxes[:file_templates][:end]
363
- end
364
- rescue Exception => e
365
- $stderr.puts "ERROR: Failed to save box Vagrantfile: " + e.message
366
- exit 1
367
- end
368
- end
369
- end
370
- end
371
-
372
- def createBoxes()
373
- $boxes[:data].each_key do |boxgroup|
374
- $boxes[:data][boxgroup].each do |box|
375
- boxFileName = ($boxes[:data][boxgroup].length > 1 ? boxgroup + "_" + ($boxes[:data][boxgroup].index(box) + 1).to_s : boxgroup)
376
-
377
- begin
378
- Dir.mktmpdir do |tmpDir|
379
- FileUtils.cd(tmpDir) do
380
- FileUtils.cp($boxes[:metadata_path], File.join(tmpDir,"metadata.json"), :preserve => true)
381
- FileUtils.cp(File.join($boxes[:dir][:vagrantfiles_root], boxFileName + ".vagrantfile"), File.join(tmpDir, "Vagrantfile"), :preserve => true)
382
-
383
- result = %x(tar -czvf "#{File.join($boxes[:dir][:boxes_root], boxFileName + ".box.tar.gz")}" Vagrantfile metadata.json)
384
-
385
- raise result if $?.exitstatus != 0
386
-
387
- FileUtils.mv(File.join($boxes[:dir][:boxes_root], boxFileName + ".box.tar.gz"), File.join($boxes[:dir][:boxes_root], boxFileName + ".box"), :force => true)
388
- FileUtils.chmod(0644, File.join($boxes[:dir][:boxes_root], boxFileName + ".box"))
389
- end
390
- end
391
- rescue Exception => e
392
- $stderr.puts "ERROR: Failed to save Vagrant box: " + e.message
393
- exit 1
394
- end
395
- end
396
- end
397
- end
398
-
399
- def main()
400
- procCliOptions()
401
- procCliArgs()
402
- getBoxData()
403
- filterBoxes()
404
- saveBoxFiles()
405
- createBoxes()
406
- end
407
-
408
- main
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
+ :username => nil
24
+ }
25
+ }
26
+
27
+ $boxes = {
28
+ :data => {},
29
+ :datacenter => nil,
30
+ :dir => {
31
+ :boxes => "boxes",
32
+ :vagrantfiles => "vagrantfiles",
33
+ :boxes_root => nil,
34
+ :output_root => File.expand_path("."),
35
+ :vagrantfiles_root => nil
36
+ },
37
+ :domain => nil,
38
+ :file_templates => {
39
+ :created_by => "# vagrant-softlayer-boxes automatic template export",
40
+ :end => "end",
41
+ :image_detail => "# Compute or flex image details:",
42
+ :indent => Hash.new() { |hash, key| hash[key] = " " * key },
43
+ :metadata_json => "{\"provider\": \"softlayer\"}",
44
+ :os_templates_avail => "# Available versions of this OS template (based on VM property selections):",
45
+ :sl_config_start => "config.vm.provider :softlayer do |sl|",
46
+ :vagrant_config_start => "Vagrant.configure(\"2\") do |config|"
47
+ },
48
+ :filter => nil,
49
+ :images => {
50
+ :private => true,
51
+ :public => true
52
+ },
53
+ :metadata_path => nil,
54
+ :monthly_billing => nil,
55
+ :templates => true,
56
+ :vlan_private => nil,
57
+ :vlan_public => nil
58
+ }
59
+
60
+ def procCliOptions()
61
+ opts = GetoptLong.new(
62
+ [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
63
+ [ '--output_dir', '-o', GetoptLong::REQUIRED_ARGUMENT ],
64
+ [ '--only_images', '-i', GetoptLong::NO_ARGUMENT ],
65
+ [ '--only_private_images', '-p', GetoptLong::NO_ARGUMENT ],
66
+ [ '--only_public_images', '-g', GetoptLong::NO_ARGUMENT ],
67
+ [ '--only_templates', '-t', GetoptLong::NO_ARGUMENT ],
68
+ [ '--default_domain', GetoptLong::REQUIRED_ARGUMENT ],
69
+ [ '--default_datacenter', GetoptLong::REQUIRED_ARGUMENT ],
70
+ [ '--default_monthly_billing', GetoptLong::NO_ARGUMENT ],
71
+ [ '--default_vlan_private', GetoptLong::REQUIRED_ARGUMENT ],
72
+ [ '--default_vlan_public', GetoptLong::REQUIRED_ARGUMENT ],
73
+ [ '--sl_api_key', '-k', GetoptLong::REQUIRED_ARGUMENT ],
74
+ [ '--sl_endpoint_url', '-e', GetoptLong::REQUIRED_ARGUMENT ],
75
+ [ '--sl_username','-u', GetoptLong::REQUIRED_ARGUMENT ]
76
+ )
77
+
78
+ opts.each do | opt, optval |
79
+ case opt
80
+ when '--help'
81
+ puts <<-EOF
82
+ vagrant-softlayer-boxes [OPTION] [FILTER]
83
+
84
+ --help, -h:
85
+ Print this help.
86
+
87
+ --sl_username USERNAME, -u USERNAME:
88
+ Sets the SoftLayer account user name. If not specified, it is assumed SL_API_USERNAME environment variable is set.
89
+
90
+ --sl_api_key SL_API_KEY, -k SL_API_KEY:
91
+ Sets the SoftLayer API key. If not specified, it is assumed SL_API_KEY environment variable is set.
92
+
93
+ --sl_endpoint_url SL_API_BASE_URL, -e SL_API_BASE_URL:
94
+ 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.
95
+ Defaults to API_PUBLIC_ENDPOINT.
96
+
97
+ --output_dir OUTPUTDIR, -o OUTPUTDIR:
98
+ Sets the root directory to create box output under.
99
+
100
+ --only_templates, -t:
101
+ Only create boxes for the CCI templates and not compute or flex images.
102
+
103
+ --only_images, -i:
104
+ Only create boxes for the compute or flex images and not the CCI templates.
105
+
106
+ --only_public_images, -g:
107
+ Only create boxes for the public compute or flex images and not the CCI templates.
108
+
109
+ --only_private_images, -p:
110
+ Only create boxes for the private compute or flex images and not the CCI templates.
111
+
112
+ --default_domain:
113
+ Set default vm domain.
114
+
115
+ --default_datacenter:
116
+ Set default vm datacenter.
117
+
118
+ --default_monthly_billing:
119
+ Set default billing type to monthly.
120
+
121
+ --default_vlan_private:
122
+ Set default vm private vlan.
123
+
124
+ --default_vlan_public:
125
+ Set default vm public vlan.
126
+
127
+ FILTER
128
+ String used to filter template and compute/flex images by name to export boxes for specific matches. Supports filtering by regular expression.
129
+
130
+ EOF
131
+
132
+ exit 0
133
+
134
+ when '--sl_username'
135
+ $sl[:sl_credentials][:username] = optval.to_s
136
+
137
+ when '--sl_api_key'
138
+ $sl[:sl_credentials][:api_key] = optval.to_s
139
+
140
+ when '--sl_endpoint_url'
141
+ if ! [ "API_PUBLIC_ENDPOINT", "API_PRIVATE_ENDPOINT" ].include?(optval.to_s.upcase)
142
+ $stderr.puts "ERROR: Invalid endpoint_url value: " + optval.to_s.upcase
143
+ exit 2
144
+ end
145
+
146
+ $sl[:sl_credentials][:endpoint_url] = (optval.to_s.upcase == 'API_PUBLIC_ENDPOINT' ? SoftLayer::API_PUBLIC_ENDPOINT : SoftLayer::API_PRIVATE_ENDPOINT )
147
+
148
+ when '--output_dir'
149
+ if File.exists?(optval.to_s) && File.ftype(optval.to_s) != 'directory'
150
+ $stderr.puts "ERROR: Path is not a directory: " + optval.to_s
151
+ exit 2
152
+ end
153
+
154
+ $boxes[:dir][:output_root] = File.expand_path(optval.to_s)
155
+ $boxes[:dir][:vagrantfiles_root] = File.join($boxes[:dir][:output_root], $boxes[:dir][:vagrantfiles])
156
+ $boxes[:dir][:boxes_root] = File.join($boxes[:dir][:output_root], $boxes[:dir][:boxes])
157
+
158
+ if File.exists?($boxes[:dir][:vagrantfiles_root]) && File.ftype($boxes[:dir][:vagrantfiles_root]) != 'directory'
159
+ $stderr.puts "ERROR: Output directory subdir is not a directory: " + $boxes[:dir][:vagrantfiles_root]
160
+ exit 2
161
+ end
162
+
163
+ if File.exists?($boxes[:dir][:boxes_root]) && File.ftype($boxes[:dir][:boxes_root]) != 'directory'
164
+ $stderr.puts "ERROR: Output directory subdir is not a directory: " + $boxes[:dir][:boxes_root]
165
+ exit 2
166
+ end
167
+
168
+ when '--only_templates'
169
+ $boxes[:images][:public] = false
170
+ $boxes[:images][:private] = false
171
+
172
+ when '--only_images'
173
+ $boxes[:templates] = false
174
+
175
+ when '--only_public_images'
176
+ $boxes[:templates] = false
177
+ $boxes[:images][:private] = false
178
+
179
+ when '--only_private_images'
180
+ $boxes[:templates] = false
181
+ $boxes[:images][:public] = false
182
+
183
+ when '--default_domain'
184
+ $boxes[:domain] = optval.to_s
185
+
186
+ when '--default_datacenter'
187
+ $boxes[:datacenter] = optval.to_s
188
+
189
+ when '--default_monthly_billing'
190
+ $boxes[:monthly_billing] = true
191
+
192
+ when '--default_vlan_private'
193
+ $boxes[:vlan_private] = optval.to_s
194
+
195
+ when'--default_vlan_public'
196
+ $boxes[:vlan_public] = optval.to_s
197
+
198
+ end
199
+ end
200
+
201
+ $boxes[:dir][:vagrantfiles_root] = File.join($boxes[:dir][:output_root], $boxes[:dir][:vagrantfiles])
202
+ $boxes[:dir][:boxes_root] = File.join($boxes[:dir][:output_root], $boxes[:dir][:boxes])
203
+ $boxes[:metadata_path] = File.join($boxes[:dir][:output_root], "metadata.json")
204
+
205
+ begin
206
+ [ $boxes[:dir][:output_root], $boxes[:dir][:vagrantfiles_root], $boxes[:dir][:boxes_root] ].each do |path|
207
+ Dir.mkdir(path, 0755) if ! File.exists?(path)
208
+ end
209
+ rescue Exception => e
210
+ $stderr.puts "ERROR: Failed to create output directories: " + e.message
211
+ exit 1
212
+ end
213
+
214
+ $sl[:sl_credentials][:username] = ENV["SL_API_USERNAME"] if $sl[:sl_credentials][:username].nil? && ENV.include?("SL_API_USERNAME")
215
+ $sl[:sl_credentials][:api_key] = ENV["SL_API_KEY"] if $sl[:sl_credentials][:api_key].nil? && ENV.include?("SL_API_KEY")
216
+
217
+ if $sl[:sl_credentials][:endpoint_url].nil? && ENV.include?("SL_API_BASE_URL")
218
+ if ! [ 'API_PRIVATE_ENDPOINT', 'API_PUBLIC_ENDPOINT' ].include?(ENV["SL_API_BASE_URL"])
219
+ $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}"
220
+ exit 2
221
+ end
222
+
223
+ $sl[:sl_credentials][:endpoint_url] = (ENV["SL_API_BASE_URL"] == "API_PUBLIC_ENDPOINT" ? SoftLayer::API_PUBLIC_ENDPOINT : SoftLayer::API_PRIVATE_ENDPOINT )
224
+ end
225
+
226
+ if $sl[:sl_credentials][:username].nil?
227
+ $stderr.puts "ERROR: No SoftLayer username specified"
228
+ exit 2
229
+ end
230
+
231
+ if $sl[:sl_credentials][:username].nil?
232
+ $stderr.puts "ERROR: No SoftLayer user name specified"
233
+ exit 2
234
+ end
235
+
236
+ if $sl[:sl_credentials][:api_key].nil?
237
+ $stderr.puts "ERROR: No SoftLayer API key specified"
238
+ exit 2
239
+ end
240
+ end
241
+
242
+ def procCliArgs()
243
+ if ARGV.length > 2
244
+ $stderr.puts "ERROR: Invalid argument supplied, please check help"
245
+ exit 2
246
+ elsif ARGV.length == 1
247
+ begin
248
+ $boxes[:filter] = Regexp.new(ARGV[0], Regexp::IGNORECASE)
249
+ rescue Exception => e
250
+ $stderr.puts "ERROR: Filter value is not a valid regular expression: " + e.message
251
+ exit 2
252
+ end
253
+ end
254
+ end
255
+
256
+ def getBoxData()
257
+ begin
258
+ $sl[:service][:virtual_guest] = SoftLayer::Service.new("SoftLayer_Virtual_Guest", $sl[:sl_credentials]) if $boxes[:templates]
259
+ $sl[:service][:account] = SoftLayer::Service.new("SoftLayer_Account", $sl[:sl_credentials]) if $boxes[:images][:private]
260
+ $sl[:service][:virtual_guest_block_device_template_group] = SoftLayer::Service.new("SoftLayer_Virtual_Guest_Block_Device_Template_Group", $sl[:sl_credentials]) if $boxes[:images][:public]
261
+ rescue Exception => e
262
+ $stderr.puts "ERROR: Failed to create SoftLayer service object: " + e.message
263
+ exit 1
264
+ end
265
+
266
+ begin
267
+ $sl[:data][:create_opts] = $sl[:service][:virtual_guest].getCreateObjectOptions if $boxes[:templates]
268
+ $sl[:data][:private_images] = $sl[:service][:account].getBlockDeviceTemplateGroups.delete_if { |block_device| ! block_device.has_key?("globalIdentifier") } if $boxes[:images][:private]
269
+ $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]
270
+ rescue Exception => e
271
+ $stderr.puts "ERROR: Failed to retrieve SoftLayer service data: " + e.message
272
+ exit 1
273
+ end
274
+
275
+ if $boxes[:templates]
276
+ $sl[:data][:create_opts]["operatingSystems"].each do |os|
277
+ boxgroup = os["template"]["operatingSystemReferenceCode"].strip.gsub(/[()]/,'').gsub(/[^a-zA-Z0-9_.-]/, '_').upcase
278
+
279
+ #We dont want to allow separate instances for templates of same group name since the only difference is additional descriptions
280
+ if ! $boxes[:data].has_key?(boxgroup)
281
+ $boxes[:data][boxgroup] = Array.new()
282
+
283
+ $boxes[:data][boxgroup].push(
284
+ {
285
+ :type => :template,
286
+ :name => os["template"]["operatingSystemReferenceCode"],
287
+ :description => [ os["itemPrice"]["item"]["description"] ]
288
+ }
289
+ )
290
+ else
291
+ $boxes[:data][boxgroup][0][:description].push(os["itemPrice"]["item"]["description"])
292
+ end
293
+ end
294
+ end
295
+
296
+ $boxes[:images].each_key do |image_view|
297
+ if $boxes[:images][image_view]
298
+ $sl[:data][(image_view == :public ? :public_images : :private_images)].each do |image|
299
+ boxgroup = image["name"].strip.gsub(/[()]/,'').gsub(/[^a-zA-Z0-9_.-]/, '_').upcase
300
+
301
+ $boxes[:data][boxgroup] = Array.new() if ! $boxes[:data].has_key?(boxgroup)
302
+ $boxes[:data][boxgroup].push(
303
+ {
304
+ :type => :block_image,
305
+ :name => image["name"],
306
+ :global_id => image["globalIdentifier"],
307
+ :note => image["note"].to_s,
308
+ :summary => image["summary"].to_s,
309
+ :visibility => image_view
310
+ }
311
+ )
312
+ end
313
+ end
314
+ end
315
+ end
316
+
317
+ def filterBoxes()
318
+ if ! $boxes[:filter].nil?
319
+ $boxes[:data].each_key do |boxgroup|
320
+ begin
321
+ $boxes[:data][boxgroup].delete_if { |box| ! box[:name].match($boxes[:filter]) }
322
+ rescue Exception => e
323
+ $stderr.puts "ERROR: Failed to filter Softlayer boxes: " + e.message
324
+ exit 1
325
+ end
326
+ end
327
+ end
328
+ end
329
+
330
+ def saveBoxFiles()
331
+ begin
332
+ File.open($boxes[:metadata_path], "w", 0644) { |fout| fout.puts $boxes[:file_templates][:metadata_json] }
333
+ rescue Exception => e
334
+ $stderr.puts "ERROR: Failed to save box metadata JSON data: " + e.message
335
+ exit 1
336
+ end
337
+
338
+ $boxes[:data].each_key do |boxgroup|
339
+ $boxes[:data][boxgroup].each do |box|
340
+ boxFileName = ($boxes[:data][boxgroup].length > 1 ? boxgroup + "_" + ($boxes[:data][boxgroup].index(box) + 1).to_s : boxgroup)
341
+
342
+ begin
343
+ File.open(File.join($boxes[:dir][:vagrantfiles_root], boxFileName + ".vagrantfile"), "w", 0644) do |fout|
344
+ fout.puts $boxes[:file_templates][:created_by]
345
+ fout.puts
346
+
347
+ fout.puts $boxes[:file_templates][:os_templates_avail] if box[:type] == :template
348
+ fout.puts box[:description].map { |descr| "# " + descr }.join("\n") if box[:type] == :template
349
+
350
+ fout.puts $boxes[:file_templates][:image_detail] if box[:type] == :block_image
351
+ fout.puts "# Global Identifier: " + box[:global_id].to_s if box[:type] == :block_image
352
+ fout.puts "# Name: " + box[:name] if box[:type] == :block_image
353
+ fout.puts "# Summary: " + box[:summary].to_s if box[:type] == :block_image
354
+ fout.puts "# Note: " + box[:note].to_s if box[:type] == :block_image
355
+ fout.puts "# Visibility: " + (box[:visibility] == :public ? "public" : "private" ) if box[:type] == :block_image
356
+
357
+ fout.puts
358
+ fout.puts $boxes[:file_templates][:vagrant_config_start]
359
+ fout.puts $boxes[:file_templates][:indent][4] + $boxes[:file_templates][:sl_config_start]
360
+
361
+ fout.puts $boxes[:file_templates][:indent][8] + "sl.datacenter = \"" + $boxes[:datacenter] + "\"" if $boxes[:datacenter]
362
+ fout.puts $boxes[:file_templates][:indent][8] + "sl.domain = \"" + $boxes[:domain] + "\"" if $boxes[:domain]
363
+ fout.puts $boxes[:file_templates][:indent][8] + "sl.hourly_billing = false" if $boxes[:monthly_billing]
364
+ fout.puts $boxes[:file_templates][:indent][8] + "sl.operating_system = \"" + box[:name] + "\"" if box[:type] == :template
365
+ fout.puts $boxes[:file_templates][:indent][8] + "sl.image_guid = \"" + box[:global_id].to_s + "\"" if box[:type] == :block_image
366
+ fout.puts $boxes[:file_templates][:indent][8] + "sl.vlan_private = \"" + $boxes[:vlan_private] + "\"" if $boxes[:vlan_private]
367
+ fout.puts $boxes[:file_templates][:indent][8] + "sl.vlan_public = \"" + $boxes[:vlan_public] + "\"" if $boxes[:vlan_public]
368
+
369
+ fout.puts $boxes[:file_templates][:indent][4] + $boxes[:file_templates][:end]
370
+ fout.puts $boxes[:file_templates][:end]
371
+ end
372
+ rescue Exception => e
373
+ $stderr.puts "ERROR: Failed to save box Vagrantfile: " + e.message
374
+ exit 1
375
+ end
376
+ end
377
+ end
378
+ end
379
+
380
+ def createBoxes()
381
+ $boxes[:data].each_key do |boxgroup|
382
+ $boxes[:data][boxgroup].each do |box|
383
+ boxFileName = ($boxes[:data][boxgroup].length > 1 ? boxgroup + "_" + ($boxes[:data][boxgroup].index(box) + 1).to_s : boxgroup)
384
+
385
+ begin
386
+ Dir.mktmpdir do |tmpDir|
387
+ FileUtils.cd(tmpDir) do
388
+ FileUtils.cp($boxes[:metadata_path], File.join(tmpDir,"metadata.json"), :preserve => true)
389
+ FileUtils.cp(File.join($boxes[:dir][:vagrantfiles_root], boxFileName + ".vagrantfile"), File.join(tmpDir, "Vagrantfile"), :preserve => true)
390
+
391
+ result = %x(tar -czvf "#{File.join($boxes[:dir][:boxes_root], boxFileName + ".box.tar.gz")}" Vagrantfile metadata.json)
392
+
393
+ raise result if $?.exitstatus != 0
394
+
395
+ FileUtils.mv(File.join($boxes[:dir][:boxes_root], boxFileName + ".box.tar.gz"), File.join($boxes[:dir][:boxes_root], boxFileName + ".box"), :force => true)
396
+ FileUtils.chmod(0644, File.join($boxes[:dir][:boxes_root], boxFileName + ".box"))
397
+ end
398
+ end
399
+ rescue Exception => e
400
+ $stderr.puts "ERROR: Failed to save Vagrant box: " + e.message
401
+ exit 1
402
+ end
403
+ end
404
+ end
405
+ end
406
+
407
+ def main()
408
+ procCliOptions()
409
+ procCliArgs()
410
+ getBoxData()
411
+ filterBoxes()
412
+ saveBoxFiles()
413
+ createBoxes()
414
+ end
415
+
416
+ main