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.
@@ -1,36 +1,38 @@
1
- require "log4r"
2
-
3
- module VagrantPlugins
4
- module SoftLayer
5
- module Action
6
- # Waits until the new machine has been rebuilt.
7
- class WaitForRebuild
8
- include Util::Warden
9
-
10
- def initialize(app, env)
11
- @app = app
12
- @logger = Log4r::Logger.new("vagrant_softlayer::action::wait_for_rebuild")
13
- end
14
-
15
- def call(env)
16
- env[:ui].info I18n.t("vagrant_softlayer.vm.wait_for_rebuild")
17
-
18
- # Defaults to 20 minutes timeout
19
- Timeout::timeout(env[:machine].provider_config.rebuild_timeout, Errors::SLRebuildTimeoutError) do
20
- @logger.debug("Checking if the instance has been rebuilt.")
21
- sl_warden do
22
- while env[:sl_machine].object_mask("activeTransactionCount").getObject["activeTransactionCount"] > 0
23
- @logger.debug("The machine is still being rebuilt. Retrying in 10 seconds.")
24
- sleep 10
25
- end
26
- end
27
- end
28
-
29
- env[:ui].info I18n.t("vagrant_softlayer.vm.rebuilt")
30
-
31
- @app.call(env)
32
- end
33
- end
34
- end
35
- end
36
- end
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module SoftLayer
5
+ module Action
6
+ # Waits until the new machine has been rebuilt.
7
+ class WaitForRebuild
8
+ include Util::Warden
9
+
10
+ def initialize(app, env)
11
+ @app = app
12
+ @logger = Log4r::Logger.new("vagrant_softlayer::action::wait_for_rebuild")
13
+ end
14
+
15
+ def call(env)
16
+ env[:ui].info I18n.t("vagrant_softlayer.vm.wait_for_rebuild")
17
+
18
+ #Rechecks every 10 sec
19
+ virtual_server = ::SoftLayer::VirtualServer.server_with_id(env[:machine].id.to_i, :client => env[:sl_client])
20
+
21
+ ready = virtual_server.wait_until_ready((env[:machine].provider_config.rebuild_timeout.to_f/10).ceil, env[:machine].provider_config.transaction_wait, 10) do |server_ready|
22
+ unless server_ready
23
+ rebuild_status = env[:sl_machine].getActiveTransaction
24
+ rebuild_status = " Rebuild status: #{rebuild_status["transactionStatus"]["friendlyName"]} (#{rebuild_status["transactionStatus"]["name"]})." if rebuild_status && ! rebuild_status.empty?
25
+ @logger.info("#{env[:machine].provider_config.hostname} is still rebuilding. Retrying in 10 seconds.#{rebuild_status}")
26
+ end
27
+ end
28
+
29
+ raise Errors::SLRebuildTimeoutError unless ready
30
+
31
+ env[:ui].info I18n.t("vagrant_softlayer.vm.rebuilt")
32
+
33
+ @app.call(env)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,268 +1,282 @@
1
- require "ostruct"
2
-
3
- module VagrantPlugins
4
- module SoftLayer
5
- class Config < Vagrant.plugin("2", :config)
6
- # The API key to access SoftLayer.
7
- attr_accessor :api_key
8
-
9
- # The endpoint SoftLayer API url.
10
- attr_accessor :endpoint_url
11
-
12
- # The username to access SoftLayer.
13
- attr_accessor :username
14
-
15
- # The datacenter shortname.
16
- attr_accessor :datacenter
17
-
18
- # Whether to allocate a dedicated instance.
19
- attr_accessor :dedicated
20
-
21
- # The disk image capacity
22
- attr_accessor :disk_capacity
23
-
24
- # The domain of the instance.
25
- attr_accessor :domain
26
-
27
- # Force the use of the private IP for all communication even if a public IP is available
28
- attr_accessor :force_private_ip
29
-
30
- # The hostname of the instance.
31
- attr_accessor :hostname
32
-
33
- # The billing type of the instance (true for hourly, false for monthly).
34
- attr_accessor :hourly_billing
35
-
36
- # The global identifier of the compute or flex image to use.
37
- attr_accessor :image_guid
38
-
39
- # The disk type of the instance (true for local, false for SAN).
40
- attr_accessor :local_disk
41
-
42
- # The amount of RAM of the instance.
43
- attr_accessor :max_memory
44
-
45
- # Network port speed in Mbps.
46
- attr_accessor :network_speed
47
-
48
- # The instance operating system identifier.
49
- attr_accessor :operating_system
50
-
51
- # URI of post-install script to download.
52
- attr_accessor :post_install
53
-
54
- # Whether or not the instance only has access to the private network.
55
- attr_accessor :private_only
56
-
57
- # The amount of time in seconds to wait for provision to complete.
58
- attr_accessor :provision_timeout
59
-
60
- # The amount of time in seconds to wait for rebuild to complete.
61
- attr_accessor :rebuild_timeout
62
-
63
- # The id or name of the ssh key to be provisioned.
64
- attr_accessor :ssh_key
65
-
66
- # The number of processors of the instance.
67
- attr_accessor :start_cpus
68
-
69
- # User defined metadata string.
70
- attr_accessor :user_data
71
-
72
- # The ID, name or qualified name of the private VLAN.
73
- attr_accessor :vlan_private
74
-
75
- # The ID, name or qualified name of the public VLAN.
76
- attr_accessor :vlan_public
77
-
78
- # The load balancers service groups to join.
79
- attr_reader :load_balancers
80
-
81
- # Automatically update DNS on create and destroy.
82
- attr_accessor :manage_dns
83
-
84
- def initialize
85
- @api_key = UNSET_VALUE
86
- @endpoint_url = UNSET_VALUE
87
- @username = UNSET_VALUE
88
-
89
- @datacenter = UNSET_VALUE
90
- @dedicated = UNSET_VALUE
91
- @disk_capacity = UNSET_VALUE
92
- @domain = UNSET_VALUE
93
- @force_private_ip = UNSET_VALUE
94
- @hostname = UNSET_VALUE
95
- @image_guid = UNSET_VALUE
96
- @hourly_billing = UNSET_VALUE
97
- @local_disk = UNSET_VALUE
98
- @max_memory = UNSET_VALUE
99
- @network_speed = UNSET_VALUE
100
- @operating_system = UNSET_VALUE
101
- @post_install = UNSET_VALUE
102
- @private_only = UNSET_VALUE
103
- @provision_timeout = UNSET_VALUE
104
- @rebuild_timeout = UNSET_VALUE
105
- @ssh_key = UNSET_VALUE
106
- @start_cpus = UNSET_VALUE
107
- @user_data = UNSET_VALUE
108
- @vlan_private = UNSET_VALUE
109
- @vlan_public = UNSET_VALUE
110
-
111
- @load_balancers = []
112
- @manage_dns = UNSET_VALUE
113
- end
114
-
115
- # Set the load balancer service group to join.
116
- #
117
- # Available options:
118
- #
119
- # :method => Routing method. Default to round robin.
120
- # :port => Load balancer virtual port.
121
- # :type => Routing type. Default to TCP.
122
- # :vip => Load balancer virtual IP address.
123
- #
124
- # An optional block will accept parameters for the
125
- # balanced service. Available parameters:
126
- #
127
- # :destination_port => TCP port on the node.
128
- # :health_check => Service health check. Default to ping.
129
- # :weight => Service weight. Default to 1.
130
- #
131
- def join_load_balancer(opts = {}, &block)
132
- # Defaults
133
- opts[:method] ||= "ROUND ROBIN"
134
- opts[:type] ||= "TCP"
135
- opts[:service] = OpenStruct.new(:destination_port => nil, :health_check => "PING", :weight => 1)
136
-
137
- yield opts[:service] if block_given?
138
-
139
- # Convert all options that belongs to
140
- # an enumeration in uppercase.
141
- opts[:method].upcase!
142
- opts[:type].upcase!
143
- opts[:service].health_check.upcase!
144
-
145
- @load_balancers << opts
146
- end
147
-
148
- def finalize!
149
- # Try to get username and api key from environment variables.
150
- # They will default to nil if the environment variables are not present.
151
- @api_key = ENV["SL_API_KEY"] if @api_key == UNSET_VALUE
152
- @username = ENV["SL_USERNAME"] if @username == UNSET_VALUE
153
-
154
- # Endpoint url defaults to public SoftLayer API url.
155
- @endpoint_url = API_PUBLIC_ENDPOINT if @endpoint_url == UNSET_VALUE
156
-
157
- # No default datacenter.
158
- @datacenter = nil if @datacenter == UNSET_VALUE
159
-
160
- # Shared instance by default.
161
- @dedicated = false if @dedicated == UNSET_VALUE
162
-
163
- # 25GB disk capacity image by default.
164
- @disk_capacity = nil if @disk_capacity == UNSET_VALUE
165
-
166
- # Domain should be specified in Vagrantfile, so we set default to nil.
167
- @domain = nil if @domain == UNSET_VALUE
168
-
169
- # Disable the use of force private IP so the default selection can take effect
170
- @force_private_ip = false if @force_private_ip == UNSET_VALUE
171
-
172
- # Hostname should be specified in Vagrantfile, either using `config.vm.hostname`
173
- # or the provider specific configuration entry.
174
- @hostname = nil if @hostname == UNSET_VALUE
175
-
176
- # Bill hourly by default.
177
- @hourly_billing = true if @hourly_billing == UNSET_VALUE
178
-
179
- # Disable the use of a specific block device image so we can leave the OS template as default
180
- @image_guid = nil if @image_guid == UNSET_VALUE
181
-
182
- # Use local disk by default.
183
- @local_disk = true if @local_disk == UNSET_VALUE
184
-
185
- # 1Gb of RAM by default.
186
- @max_memory = 1024 if @max_memory == UNSET_VALUE
187
-
188
- # 10Mbps by default.
189
- @network_speed = 10 if @network_speed == UNSET_VALUE
190
-
191
- # Provision with the latest Ubuntu by default.
192
- @operating_system = "UBUNTU_LATEST" if @operating_system == UNSET_VALUE
193
-
194
- # No post install script by default.
195
- @post_install = nil if @post_install == UNSET_VALUE
196
-
197
- # Private-network only is false by default.
198
- @private_only = false if @private_only == UNSET_VALUE
199
-
200
- # The amount of time in seconds to wait for provision to complete.
201
- @provision_timeout = 1200 if @provision_timeout == UNSET_VALUE
202
-
203
- # The amount of time in seconds to wait for rebuild to complete.
204
- @rebuild_timeout = 1200 if @rebuild_timeout == UNSET_VALUE
205
-
206
- # SSH key should be specified in Vagrantfile, so we set default to nil.
207
- @ssh_key = nil if @ssh_key == UNSET_VALUE
208
-
209
- # One processor by default.
210
- @start_cpus = 1 if @start_cpus == UNSET_VALUE
211
-
212
- # No user metadata by default.
213
- @user_data = nil if @user_data == UNSET_VALUE
214
-
215
- # No specific private VLAN by default.
216
- @vlan_private = nil if @vlan_private == UNSET_VALUE
217
-
218
- # No specific public VLAN by default.
219
- @vlan_public = nil if @vlan_public == UNSET_VALUE
220
-
221
- # DNS management off by default
222
- @manage_dns = false if @manage_dns == UNSET_VALUE
223
- end
224
-
225
- # Aliases for ssh_key for beautiful semantic.
226
- def ssh_keys=(value)
227
- @ssh_key = value
228
- end
229
-
230
- alias_method :ssh_key_id=, :ssh_keys=
231
- alias_method :ssh_key_ids=, :ssh_keys=
232
- alias_method :ssh_key_name=, :ssh_keys=
233
- alias_method :ssh_key_names=, :ssh_keys=
234
-
235
- def validate(machine)
236
- errors = []
237
-
238
- errors << I18n.t("vagrant_softlayer.config.api_key_required") if !@api_key
239
- errors << I18n.t("vagrant_softlayer.config.username_required") if !@username
240
-
241
- errors << I18n.t("vagrant_softlayer.config.domain_required") if !@domain
242
- errors << I18n.t("vagrant_softlayer.config.ssh_key_required") if !@ssh_key
243
-
244
- errors << I18n.t("vagrant_softlayer.config.img_guid_os_code_mutually_exclusive") if @image_guid && @operating_system
245
- errors << I18n.t("vagrant_softlayer.config.img_guid_capacity_mutually_exclusive") if @image_guid && @disk_capacity
246
-
247
- # Fail if both `vm.hostname` and `provider.hostname` are nil.
248
- if !@hostname && !machine.config.vm.hostname
249
- errors << I18n.t("vagrant_softlayer.config.hostname_required")
250
- end
251
-
252
- # Fail if a load balancer has been specified without vip, port or destination port.
253
- unless @load_balancers.empty?
254
- @load_balancers.each do |lb|
255
- errors << I18n.t("vagrant_softlayer.config.lb_port_vip_required") unless (lb[:vip] && lb[:port] && lb[:service].destination_port)
256
- end
257
- end
258
-
259
- # Fail if two or more load balancers has been specified with same vip and port.
260
- if @load_balancers.map { |lb| { :port => lb[:port], :vip => lb[:vip] } }.uniq!
261
- errors << I18n.t("vagrant_softlayer.config.lb_duplicate")
262
- end
263
-
264
- { "SoftLayer" => errors }
265
- end
266
- end
267
- end
268
- end
1
+ require "ostruct"
2
+
3
+ module VagrantPlugins
4
+ module SoftLayer
5
+ class Config < Vagrant.plugin("2", :config)
6
+ # The API key to access SoftLayer.
7
+ attr_accessor :api_key
8
+
9
+ # Th SoftLayer API request timeout value in seconds
10
+ attr_accessor :api_timeout
11
+
12
+ # The endpoint SoftLayer API url.
13
+ attr_accessor :endpoint_url
14
+
15
+ # The username to access SoftLayer.
16
+ attr_accessor :username
17
+
18
+ # The datacenter shortname.
19
+ attr_accessor :datacenter
20
+
21
+ # Whether to allocate a dedicated instance.
22
+ attr_accessor :dedicated
23
+
24
+ # The disk image capacity
25
+ attr_accessor :disk_capacity
26
+
27
+ # The domain of the instance.
28
+ attr_accessor :domain
29
+
30
+ # Force the use of the private IP for all communication even if a public IP is available
31
+ attr_accessor :force_private_ip
32
+
33
+ # The hostname of the instance.
34
+ attr_accessor :hostname
35
+
36
+ # The billing type of the instance (true for hourly, false for monthly).
37
+ attr_accessor :hourly_billing
38
+
39
+ # The global identifier of the compute or flex image to use.
40
+ attr_accessor :image_guid
41
+
42
+ # The disk type of the instance (true for local, false for SAN).
43
+ attr_accessor :local_disk
44
+
45
+ # The amount of RAM of the instance.
46
+ attr_accessor :max_memory
47
+
48
+ # Network port speed in Mbps.
49
+ attr_accessor :network_speed
50
+
51
+ # The instance operating system identifier.
52
+ attr_accessor :operating_system
53
+
54
+ # URI of post-install script to download.
55
+ attr_accessor :post_install
56
+
57
+ # Whether or not the instance only has access to the private network.
58
+ attr_accessor :private_only
59
+
60
+ # The amount of time in seconds to wait for provision to complete.
61
+ attr_accessor :provision_timeout
62
+
63
+ # The amount of time in seconds to wait for rebuild to complete.
64
+ attr_accessor :rebuild_timeout
65
+
66
+ # The id or name of the ssh key to be provisioned.
67
+ attr_accessor :ssh_key
68
+
69
+ # The number of processors of the instance.
70
+ attr_accessor :start_cpus
71
+
72
+ # Whether to wait for transaction completion on actions that place orders
73
+ attr_accessor :transaction_wait
74
+
75
+ # User defined metadata string.
76
+ attr_accessor :user_data
77
+
78
+ # The ID, name or qualified name of the private VLAN.
79
+ attr_accessor :vlan_private
80
+
81
+ # The ID, name or qualified name of the public VLAN.
82
+ attr_accessor :vlan_public
83
+
84
+ # The load balancers service groups to join.
85
+ attr_reader :load_balancers
86
+
87
+ # Automatically update DNS on create and destroy.
88
+ attr_accessor :manage_dns
89
+
90
+ def initialize
91
+ @api_key = UNSET_VALUE
92
+ @api_timeout = UNSET_VALUE
93
+ @endpoint_url = UNSET_VALUE
94
+ @username = UNSET_VALUE
95
+
96
+ @datacenter = UNSET_VALUE
97
+ @dedicated = UNSET_VALUE
98
+ @disk_capacity = UNSET_VALUE
99
+ @domain = UNSET_VALUE
100
+ @force_private_ip = UNSET_VALUE
101
+ @hostname = UNSET_VALUE
102
+ @image_guid = UNSET_VALUE
103
+ @hourly_billing = UNSET_VALUE
104
+ @local_disk = UNSET_VALUE
105
+ @max_memory = UNSET_VALUE
106
+ @network_speed = UNSET_VALUE
107
+ @operating_system = UNSET_VALUE
108
+ @post_install = UNSET_VALUE
109
+ @private_only = UNSET_VALUE
110
+ @provision_timeout = UNSET_VALUE
111
+ @rebuild_timeout = UNSET_VALUE
112
+ @ssh_key = UNSET_VALUE
113
+ @start_cpus = UNSET_VALUE
114
+ @transaction_wait = UNSET_VALUE
115
+ @user_data = UNSET_VALUE
116
+ @vlan_private = UNSET_VALUE
117
+ @vlan_public = UNSET_VALUE
118
+
119
+ @load_balancers = []
120
+ @manage_dns = UNSET_VALUE
121
+ end
122
+
123
+ # Set the load balancer service group to join.
124
+ #
125
+ # Available options:
126
+ #
127
+ # :method => Routing method. Default to round robin.
128
+ # :port => Load balancer virtual port.
129
+ # :type => Routing type. Default to TCP.
130
+ # :vip => Load balancer virtual IP address.
131
+ #
132
+ # An optional block will accept parameters for the
133
+ # balanced service. Available parameters:
134
+ #
135
+ # :destination_port => TCP port on the node.
136
+ # :health_check => Service health check. Default to ping.
137
+ # :weight => Service weight. Default to 1.
138
+ #
139
+ def join_load_balancer(opts = {}, &block)
140
+ # Defaults
141
+ opts[:method] ||= "ROUND ROBIN"
142
+ opts[:type] ||= "TCP"
143
+ opts[:service] = OpenStruct.new(:destination_port => nil, :health_check => "PING", :weight => 1)
144
+
145
+ yield opts[:service] if block_given?
146
+
147
+ # Convert all options that belongs to
148
+ # an enumeration in uppercase.
149
+ opts[:method].upcase!
150
+ opts[:type].upcase!
151
+ opts[:service].health_check.upcase!
152
+
153
+ @load_balancers << opts
154
+ end
155
+
156
+ def finalize!
157
+ # Try to get username and api key from environment variables.
158
+ # They will default to nil if the environment variables are not present.
159
+ @api_key = ENV["SL_API_KEY"] if @api_key == UNSET_VALUE
160
+ @username = ENV["SL_USERNAME"] if @username == UNSET_VALUE
161
+
162
+ # Th SoftLayer API request timeout value in seconds
163
+ @api_timeout = 60 if @api_timeout == UNSET_VALUE
164
+
165
+ # Endpoint url defaults to public SoftLayer API url.
166
+ @endpoint_url = API_PUBLIC_ENDPOINT if @endpoint_url == UNSET_VALUE
167
+
168
+ # No default datacenter.
169
+ @datacenter = nil if @datacenter == UNSET_VALUE
170
+
171
+ # Shared instance by default.
172
+ @dedicated = false if @dedicated == UNSET_VALUE
173
+
174
+ # 25GB disk capacity image by default.
175
+ @disk_capacity = nil if @disk_capacity == UNSET_VALUE
176
+
177
+ # Domain should be specified in Vagrantfile, so we set default to nil.
178
+ @domain = nil if @domain == UNSET_VALUE
179
+
180
+ # Disable the use of force private IP so the default selection can take effect
181
+ @force_private_ip = false if @force_private_ip == UNSET_VALUE
182
+
183
+ # Hostname should be specified in Vagrantfile, either using `config.vm.hostname`
184
+ # or the provider specific configuration entry.
185
+ @hostname = nil if @hostname == UNSET_VALUE
186
+
187
+ # Bill hourly by default.
188
+ @hourly_billing = true if @hourly_billing == UNSET_VALUE
189
+
190
+ # Disable the use of a specific block device image so we can leave the OS template as default
191
+ @image_guid = nil if @image_guid == UNSET_VALUE
192
+
193
+ # Use local disk by default.
194
+ @local_disk = true if @local_disk == UNSET_VALUE
195
+
196
+ # 1Gb of RAM by default.
197
+ @max_memory = 1024 if @max_memory == UNSET_VALUE
198
+
199
+ # 10Mbps by default.
200
+ @network_speed = 10 if @network_speed == UNSET_VALUE
201
+
202
+ # Provision with the latest Ubuntu by default.
203
+ @operating_system = "UBUNTU_LATEST" if @operating_system == UNSET_VALUE
204
+
205
+ # No post install script by default.
206
+ @post_install = nil if @post_install == UNSET_VALUE
207
+
208
+ # Private-network only is false by default.
209
+ @private_only = false if @private_only == UNSET_VALUE
210
+
211
+ # The amount of time in seconds to wait for provision to complete.
212
+ @provision_timeout = 1200 if @provision_timeout == UNSET_VALUE
213
+
214
+ # The amount of time in seconds to wait for rebuild to complete.
215
+ @rebuild_timeout = 1200 if @rebuild_timeout == UNSET_VALUE
216
+
217
+ # SSH key should be specified in Vagrantfile, so we set default to nil.
218
+ @ssh_key = nil if @ssh_key == UNSET_VALUE
219
+
220
+ # One processor by default.
221
+ @start_cpus = 1 if @start_cpus == UNSET_VALUE
222
+
223
+ # Whether to wait for transaction completion on actions that place orders
224
+ @transaction_wait = true if @start_cpus == UNSET_VALUE
225
+
226
+ # No user metadata by default.
227
+ @user_data = nil if @user_data == UNSET_VALUE
228
+
229
+ # No specific private VLAN by default.
230
+ @vlan_private = nil if @vlan_private == UNSET_VALUE
231
+
232
+ # No specific public VLAN by default.
233
+ @vlan_public = nil if @vlan_public == UNSET_VALUE
234
+
235
+ # DNS management off by default
236
+ @manage_dns = false if @manage_dns == UNSET_VALUE
237
+ end
238
+
239
+ # Aliases for ssh_key for beautiful semantic.
240
+ def ssh_keys=(value)
241
+ @ssh_key = value
242
+ end
243
+
244
+ alias_method :ssh_key_id=, :ssh_keys=
245
+ alias_method :ssh_key_ids=, :ssh_keys=
246
+ alias_method :ssh_key_name=, :ssh_keys=
247
+ alias_method :ssh_key_names=, :ssh_keys=
248
+
249
+ def validate(machine)
250
+ errors = []
251
+
252
+ errors << I18n.t("vagrant_softlayer.config.api_key_required") if !@api_key
253
+ errors << I18n.t("vagrant_softlayer.config.username_required") if !@username
254
+
255
+ errors << I18n.t("vagrant_softlayer.config.domain_required") if !@domain
256
+ errors << I18n.t("vagrant_softlayer.config.ssh_key_required") if !@ssh_key
257
+
258
+ errors << I18n.t("vagrant_softlayer.config.img_guid_os_code_mutually_exclusive") if @image_guid && @operating_system
259
+ errors << I18n.t("vagrant_softlayer.config.img_guid_capacity_mutually_exclusive") if @image_guid && @disk_capacity
260
+
261
+ # Fail if both `vm.hostname` and `provider.hostname` are nil.
262
+ if !@hostname && !machine.config.vm.hostname
263
+ errors << I18n.t("vagrant_softlayer.config.hostname_required")
264
+ end
265
+
266
+ # Fail if a load balancer has been specified without vip, port or destination port.
267
+ unless @load_balancers.empty?
268
+ @load_balancers.each do |lb|
269
+ errors << I18n.t("vagrant_softlayer.config.lb_port_vip_required") unless (lb[:vip] && lb[:port] && lb[:service].destination_port)
270
+ end
271
+ end
272
+
273
+ # Fail if two or more load balancers has been specified with same vip and port.
274
+ if @load_balancers.map { |lb| { :port => lb[:port], :vip => lb[:vip] } }.uniq!
275
+ errors << I18n.t("vagrant_softlayer.config.lb_duplicate")
276
+ end
277
+
278
+ { "SoftLayer" => errors }
279
+ end
280
+ end
281
+ end
282
+ end