vagrant-gq 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/Gemfile +14 -0
  4. data/LICENSE +22 -0
  5. data/README.md +169 -0
  6. data/Rakefile +21 -0
  7. data/example_box/README.md +13 -0
  8. data/example_box/metadata.json +3 -0
  9. data/greenqloud-generic.box +0 -0
  10. data/lib/vagrant-gq/action/connect_gq.rb +47 -0
  11. data/lib/vagrant-gq/action/is_created.rb +18 -0
  12. data/lib/vagrant-gq/action/is_stopped.rb +18 -0
  13. data/lib/vagrant-gq/action/message_already_created.rb +16 -0
  14. data/lib/vagrant-gq/action/message_not_created.rb +16 -0
  15. data/lib/vagrant-gq/action/message_will_not_destroy.rb +16 -0
  16. data/lib/vagrant-gq/action/read_ssh_info.rb +53 -0
  17. data/lib/vagrant-gq/action/read_state.rb +38 -0
  18. data/lib/vagrant-gq/action/run_instance.rb +247 -0
  19. data/lib/vagrant-gq/action/start_instance.rb +81 -0
  20. data/lib/vagrant-gq/action/stop_instance.rb +28 -0
  21. data/lib/vagrant-gq/action/sync_folders.rb +118 -0
  22. data/lib/vagrant-gq/action/terminate_instance.rb +47 -0
  23. data/lib/vagrant-gq/action/timed_provision.rb +21 -0
  24. data/lib/vagrant-gq/action/wait_for_state.rb +41 -0
  25. data/lib/vagrant-gq/action/warn_networks.rb +19 -0
  26. data/lib/vagrant-gq/action.rb +190 -0
  27. data/lib/vagrant-gq/config.rb +372 -0
  28. data/lib/vagrant-gq/errors.rb +31 -0
  29. data/lib/vagrant-gq/plugin.rb +73 -0
  30. data/lib/vagrant-gq/provider.rb +50 -0
  31. data/lib/vagrant-gq/util/timer.rb +17 -0
  32. data/lib/vagrant-gq/version.rb +5 -0
  33. data/lib/vagrant-gq.rb +18 -0
  34. data/locales/en.yml +122 -0
  35. data/spec/vagrant-gq/config_spec.rb +216 -0
  36. data/vagrant-gq.gemspec +58 -0
  37. metadata +148 -0
@@ -0,0 +1,190 @@
1
+ require "pathname"
2
+
3
+ require "vagrant/action/builder"
4
+
5
+ module VagrantPlugins
6
+ module GQ
7
+ module Action
8
+ # Include the built-in modules so we can use them as top-level things.
9
+ include Vagrant::Action::Builtin
10
+
11
+ # This action is called to halt the remote machine.
12
+ def self.action_halt
13
+ Vagrant::Action::Builder.new.tap do |b|
14
+ b.use ConfigValidate
15
+ b.use Call, IsCreated do |env, b2|
16
+ if !env[:result]
17
+ b2.use MessageNotCreated
18
+ next
19
+ end
20
+
21
+ b2.use ConnectGQ
22
+ b2.use StopInstance
23
+ end
24
+ end
25
+ end
26
+
27
+ # This action is called to terminate the remote machine.
28
+ def self.action_destroy
29
+ Vagrant::Action::Builder.new.tap do |b|
30
+ b.use Call, DestroyConfirm do |env, b2|
31
+ if env[:result]
32
+ b2.use ConfigValidate
33
+ b.use Call, IsCreated do |env2, b3|
34
+ if !env2[:result]
35
+ b3.use MessageNotCreated
36
+ next
37
+ end
38
+ end
39
+ b2.use ConnectGQ
40
+ b2.use TerminateInstance
41
+ b2.use ProvisionerCleanup if defined?(ProvisionerCleanup)
42
+ else
43
+ b2.use MessageWillNotDestroy
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ # This action is called when `vagrant provision` is called.
50
+ def self.action_provision
51
+ Vagrant::Action::Builder.new.tap do |b|
52
+ b.use ConfigValidate
53
+ b.use Call, IsCreated do |env, b2|
54
+ if !env[:result]
55
+ b2.use MessageNotCreated
56
+ next
57
+ end
58
+
59
+ b2.use Provision
60
+ b2.use SyncFolders
61
+ end
62
+ end
63
+ end
64
+
65
+ # This action is called to read the SSH info of the machine. The
66
+ # resulting state is expected to be put into the `:machine_ssh_info`
67
+ # key.
68
+ def self.action_read_ssh_info
69
+ Vagrant::Action::Builder.new.tap do |b|
70
+ b.use ConfigValidate
71
+ b.use ConnectGQ
72
+ b.use ReadSSHInfo
73
+ end
74
+ end
75
+
76
+ # This action is called to read the state of the machine. The
77
+ # resulting state is expected to be put into the `:machine_state_id`
78
+ # key.
79
+ def self.action_read_state
80
+ Vagrant::Action::Builder.new.tap do |b|
81
+ b.use ConfigValidate
82
+ b.use ConnectGQ
83
+ b.use ReadState
84
+ end
85
+ end
86
+
87
+ # This action is called to SSH into the machine.
88
+ def self.action_ssh
89
+ Vagrant::Action::Builder.new.tap do |b|
90
+ b.use ConfigValidate
91
+ b.use Call, IsCreated do |env, b2|
92
+ if !env[:result]
93
+ b2.use MessageNotCreated
94
+ next
95
+ end
96
+
97
+ b2.use SSHExec
98
+ end
99
+ end
100
+ end
101
+
102
+ def self.action_ssh_run
103
+ Vagrant::Action::Builder.new.tap do |b|
104
+ b.use ConfigValidate
105
+ b.use Call, IsCreated do |env, b2|
106
+ if !env[:result]
107
+ b2.use MessageNotCreated
108
+ next
109
+ end
110
+
111
+ b2.use SSHRun
112
+ end
113
+ end
114
+ end
115
+
116
+ def self.action_prepare_boot
117
+ Vagrant::Action::Builder.new.tap do |b|
118
+ b.use Provision
119
+ b.use SyncFolders
120
+ b.use WarnNetworks
121
+ end
122
+ end
123
+
124
+ # This action is called to bring the box up from nothing.
125
+ def self.action_up
126
+ Vagrant::Action::Builder.new.tap do |b|
127
+ b.use HandleBoxUrl
128
+ b.use ConfigValidate
129
+ b.use ConnectGQ
130
+ b.use Call, IsCreated do |env1, b1|
131
+ if env1[:result]
132
+ b1.use Call, IsStopped do |env2, b2|
133
+ if env2[:result]
134
+ b2.use action_prepare_boot
135
+ b2.use StartInstance # restart this instance
136
+ else
137
+ b2.use MessageAlreadyCreated # TODO write a better message
138
+ end
139
+ end
140
+ else
141
+ b1.use action_prepare_boot
142
+ b1.use RunInstance # launch a new instance
143
+ end
144
+ end
145
+ end
146
+ end
147
+
148
+ def self.action_reload
149
+ Vagrant::Action::Builder.new.tap do |b|
150
+ b.use ConfigValidate
151
+ b.use ConnectGQ
152
+ b.use Call, IsCreated do |env, b2|
153
+ if !env[:result]
154
+ b2.use MessageNotCreated
155
+ next
156
+ end
157
+
158
+ b2.use action_halt
159
+ b2.use Call, WaitForState, :stopped, 120 do |env2, b3|
160
+ if env2[:result]
161
+ b3.use action_up
162
+ else
163
+ # TODO we couldn't reach :stopped, what now?
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+
170
+ # The autoload farm
171
+ action_root = Pathname.new(File.expand_path("../action", __FILE__))
172
+ autoload :ConnectGQ, action_root.join("connect_gq")
173
+ autoload :IsCreated, action_root.join("is_created")
174
+ autoload :IsStopped, action_root.join("is_stopped")
175
+ autoload :MessageAlreadyCreated, action_root.join("message_already_created")
176
+ autoload :MessageNotCreated, action_root.join("message_not_created")
177
+ autoload :MessageWillNotDestroy, action_root.join("message_will_not_destroy")
178
+ autoload :ReadSSHInfo, action_root.join("read_ssh_info")
179
+ autoload :ReadState, action_root.join("read_state")
180
+ autoload :RunInstance, action_root.join("run_instance")
181
+ autoload :StartInstance, action_root.join("start_instance")
182
+ autoload :StopInstance, action_root.join("stop_instance")
183
+ autoload :SyncFolders, action_root.join("sync_folders")
184
+ autoload :TerminateInstance, action_root.join("terminate_instance")
185
+ autoload :TimedProvision, action_root.join("timed_provision") # some plugins now expect this action to exist
186
+ autoload :WaitForState, action_root.join("wait_for_state")
187
+ autoload :WarnNetworks, action_root.join("warn_networks")
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,372 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module GQ
5
+ class Config < Vagrant.plugin("2", :config)
6
+ # The access key ID for accessing GQ.
7
+ #
8
+ # @return [String]
9
+ attr_accessor :access_key_id
10
+
11
+ # The ID of the AMI to use.
12
+ #
13
+ # @return [String]
14
+ attr_accessor :qmi
15
+
16
+ # The availability zone to launch the instance into. If nil, it will
17
+ # use the default for your account.
18
+ #
19
+ # @return [String]
20
+ attr_accessor :availability_zone
21
+
22
+ # The timeout to wait for an instance to become ready.
23
+ #
24
+ # @return [Fixnum]
25
+ attr_accessor :instance_ready_timeout
26
+
27
+ # The type of instance to launch, such as "m1.small"
28
+ #
29
+ # @return [String]
30
+ attr_accessor :instance_type
31
+
32
+ # The name of the keypair to use.
33
+ #
34
+ # @return [String]
35
+ attr_accessor :keypair_name
36
+
37
+ # The private IP address to give this machine (VPC).
38
+ #
39
+ # @return [String]
40
+ attr_accessor :private_ip_address
41
+
42
+ # Acquire and attach an elastic IP address (VPC).
43
+ #
44
+ # @return [Boolean]
45
+ attr_accessor :elastic_ip
46
+
47
+ # The name of the GQ region in which to create the instance.
48
+ #
49
+ # @return [String]
50
+ attr_accessor :region
51
+
52
+ # The EC2 endpoint to connect to
53
+ #
54
+ # @return [String]
55
+ attr_accessor :endpoint
56
+
57
+ # The version of the GQ api to use
58
+ #
59
+ # @return [String]
60
+ attr_accessor :version
61
+
62
+ # The secret access key for accessing GQ.
63
+ #
64
+ # @return [String]
65
+ attr_accessor :secret_access_key
66
+
67
+ # The security groups to set on the instance. For VPC this must
68
+ # be a list of IDs. For EC2, it can be either.
69
+ #
70
+ # @return [Array<String>]
71
+ attr_reader :security_groups
72
+
73
+ # The Amazon resource name (ARN) of the IAM Instance Profile
74
+ # to associate with the instance.
75
+ #
76
+ # @return [String]
77
+ attr_accessor :iam_instance_profile_arn
78
+
79
+ # The name of the IAM Instance Profile to associate with
80
+ # the instance.
81
+ #
82
+ # @return [String]
83
+ attr_accessor :iam_instance_profile_name
84
+
85
+ # The subnet ID to launch the machine into (VPC).
86
+ #
87
+ # @return [String]
88
+ attr_accessor :subnet_id
89
+
90
+ # The tags for the machine.
91
+ #
92
+ # @return [Hash<String, String>]
93
+ attr_accessor :tags
94
+
95
+ # Use IAM Instance Role for authentication to GQ instead of an
96
+ # explicit access_id and secret_access_key
97
+ #
98
+ # @return [Boolean]
99
+ attr_accessor :use_iam_profile
100
+
101
+ # The user data string
102
+ #
103
+ # @return [String]
104
+ attr_accessor :user_data
105
+
106
+ # Block device mappings
107
+ #
108
+ # @return [Array<Hash>]
109
+ attr_accessor :block_device_mapping
110
+
111
+ # Indicates whether an instance stops or terminates when you initiate shutdown from the instance
112
+ #
113
+ # @return [bool]
114
+ attr_accessor :terminate_on_shutdown
115
+
116
+ # Specifies which address to connect to with ssh
117
+ # Must be one of:
118
+ # - :public_ip_address
119
+ # - :dns_name
120
+ # - :private_ip_address
121
+ # This attribute also accepts an array of symbols
122
+ #
123
+ # @return [Symbol]
124
+ attr_accessor :ssh_host_attribute
125
+
126
+ # Enables Monitoring
127
+ #
128
+ # @return [Boolean]
129
+ attr_accessor :monitoring
130
+
131
+ # EBS optimized instance
132
+ #
133
+ # @return [Boolean]
134
+ attr_accessor :ebs_optimized
135
+
136
+ # Assigning a public IP address in a VPC
137
+ #
138
+ # @return [Boolean]
139
+ attr_accessor :associate_public_ip
140
+
141
+ def initialize(region_specific=false)
142
+ @access_key_id = UNSET_VALUE
143
+ @qmi = UNSET_VALUE
144
+ @availability_zone = UNSET_VALUE
145
+ @instance_ready_timeout = UNSET_VALUE
146
+ @instance_type = UNSET_VALUE
147
+ @keypair_name = UNSET_VALUE
148
+ @private_ip_address = UNSET_VALUE
149
+ @region = UNSET_VALUE
150
+ @endpoint = UNSET_VALUE
151
+ @version = UNSET_VALUE
152
+ @secret_access_key = UNSET_VALUE
153
+ @security_groups = UNSET_VALUE
154
+ @subnet_id = UNSET_VALUE
155
+ @tags = {}
156
+ @user_data = UNSET_VALUE
157
+ @use_iam_profile = UNSET_VALUE
158
+ @block_device_mapping = []
159
+ @elastic_ip = UNSET_VALUE
160
+ @iam_instance_profile_arn = UNSET_VALUE
161
+ @iam_instance_profile_name = UNSET_VALUE
162
+ @terminate_on_shutdown = UNSET_VALUE
163
+ @ssh_host_attribute = UNSET_VALUE
164
+ @monitoring = UNSET_VALUE
165
+ @ebs_optimized = UNSET_VALUE
166
+ @associate_public_ip = UNSET_VALUE
167
+
168
+ # Internal state (prefix with __ so they aren't automatically
169
+ # merged)
170
+ @__compiled_region_configs = {}
171
+ @__finalized = false
172
+ @__region_config = {}
173
+ @__region_specific = region_specific
174
+ end
175
+
176
+ # set security_groups
177
+ def security_groups=(value)
178
+ # convert value to array if necessary
179
+ @security_groups = value.is_a?(Array) ? value : [value]
180
+ end
181
+
182
+ # Allows region-specific overrides of any of the settings on this
183
+ # configuration object. This allows the user to override things like
184
+ # AMI and keypair name for regions. Example:
185
+ #
186
+ # gq.region_config "us-east-1" do |region|
187
+ # region.qmi = "qmi-12345678"
188
+ # region.keypair_name = "company-east"
189
+ # end
190
+ #
191
+ # @param [String] region The region name to configure.
192
+ # @param [Hash] attributes Direct attributes to set on the configuration
193
+ # as a shortcut instead of specifying a full block.
194
+ # @yield [config] Yields a new GQ configuration.
195
+ def region_config(region, attributes=nil, &block)
196
+ # Append the block to the list of region configs for that region.
197
+ # We'll evaluate these upon finalization.
198
+ @__region_config[region] ||= []
199
+
200
+ # Append a block that sets attributes if we got one
201
+ if attributes
202
+ attr_block = lambda do |config|
203
+ config.set_options(attributes)
204
+ end
205
+
206
+ @__region_config[region] << attr_block
207
+ end
208
+
209
+ # Append a block if we got one
210
+ @__region_config[region] << block if block_given?
211
+ end
212
+
213
+ #-------------------------------------------------------------------
214
+ # Internal methods.
215
+ #-------------------------------------------------------------------
216
+
217
+ def merge(other)
218
+ super.tap do |result|
219
+ # Copy over the region specific flag. "True" is retained if either
220
+ # has it.
221
+ new_region_specific = other.instance_variable_get(:@__region_specific)
222
+ result.instance_variable_set(
223
+ :@__region_specific, new_region_specific || @__region_specific)
224
+
225
+ # Go through all the region configs and prepend ours onto
226
+ # theirs.
227
+ new_region_config = other.instance_variable_get(:@__region_config)
228
+ @__region_config.each do |key, value|
229
+ new_region_config[key] ||= []
230
+ new_region_config[key] = value + new_region_config[key]
231
+ end
232
+
233
+ # Set it
234
+ result.instance_variable_set(:@__region_config, new_region_config)
235
+
236
+ # Merge in the tags
237
+ result.tags.merge!(self.tags)
238
+ result.tags.merge!(other.tags)
239
+
240
+ # Merge block_device_mapping
241
+ result.block_device_mapping |= self.block_device_mapping
242
+ result.block_device_mapping |= other.block_device_mapping
243
+ end
244
+ end
245
+
246
+ def finalize!
247
+ # Try to get access keys from standard GQ environment variables; they
248
+ # will default to nil if the environment variables are not present.
249
+ @access_key_id = ENV['EC2_ACCESS_KEY'] if @access_key_id == UNSET_VALUE
250
+ @secret_access_key = ENV['EC2_SECRET_KEY'] if @secret_access_key == UNSET_VALUE
251
+
252
+ # AMI must be nil, since we can't default that
253
+ @qmi = nil if @qmi == UNSET_VALUE
254
+
255
+ # Set the default timeout for waiting for an instance to be ready
256
+ @instance_ready_timeout = 120 if @instance_ready_timeout == UNSET_VALUE
257
+
258
+ # Default instance type is an m1.small
259
+ @instance_type = "m1.small" if @instance_type == UNSET_VALUE
260
+
261
+ # Keypair defaults to nil
262
+ @keypair_name = nil if @keypair_name == UNSET_VALUE
263
+
264
+ # Default the private IP to nil since VPC is not default
265
+ @private_ip_address = nil if @private_ip_address == UNSET_VALUE
266
+
267
+ # Acquire an elastic IP if requested
268
+ @elastic_ip = nil if @elastic_ip == UNSET_VALUE
269
+
270
+ # Default region is us-east-1. This is sensible because GQ
271
+ # generally defaults to this as well.
272
+ @region = "us-east-1" if @region == UNSET_VALUE
273
+ @availability_zone = nil if @availability_zone == UNSET_VALUE
274
+ @endpoint = nil if @endpoint == UNSET_VALUE
275
+ @version = nil if @version == UNSET_VALUE
276
+
277
+ # The security groups are empty by default.
278
+ @security_groups = [] if @security_groups == UNSET_VALUE
279
+
280
+ # Subnet is nil by default otherwise we'd launch into VPC.
281
+ @subnet_id = nil if @subnet_id == UNSET_VALUE
282
+
283
+ # IAM Instance profile arn/name is nil by default.
284
+ @iam_instance_profile_arn = nil if @iam_instance_profile_arn == UNSET_VALUE
285
+ @iam_instance_profile_name = nil if @iam_instance_profile_name == UNSET_VALUE
286
+
287
+ # By default we don't use an IAM profile
288
+ @use_iam_profile = false if @use_iam_profile == UNSET_VALUE
289
+
290
+ # User Data is nil by default
291
+ @user_data = nil if @user_data == UNSET_VALUE
292
+
293
+ # default false
294
+ @terminate_on_shutdown = false if @terminate_on_shutdown == UNSET_VALUE
295
+
296
+ # default to nil
297
+ @ssh_host_attribute = nil if @ssh_host_attribute == UNSET_VALUE
298
+
299
+ # default false
300
+ @monitoring = false if @monitoring == UNSET_VALUE
301
+
302
+ # default false
303
+ @ebs_optimized = false if @ebs_optimized == UNSET_VALUE
304
+
305
+ # default false
306
+ @associate_public_ip = false if @associate_public_ip == UNSET_VALUE
307
+
308
+ # Compile our region specific configurations only within
309
+ # NON-REGION-SPECIFIC configurations.
310
+ if !@__region_specific
311
+ @__region_config.each do |region, blocks|
312
+ config = self.class.new(true).merge(self)
313
+
314
+ # Execute the configuration for each block
315
+ blocks.each { |b| b.call(config) }
316
+
317
+ # The region name of the configuration always equals the
318
+ # region config name:
319
+ config.region = region
320
+
321
+ # Finalize the configuration
322
+ config.finalize!
323
+
324
+ # Store it for retrieval
325
+ @__compiled_region_configs[region] = config
326
+ end
327
+ end
328
+
329
+ # Mark that we finalized
330
+ @__finalized = true
331
+ end
332
+
333
+ def validate(machine)
334
+ errors = _detected_errors
335
+
336
+ errors << I18n.t("vagrant_gq.config.region_required") if @region.nil?
337
+
338
+ if @region
339
+ # Get the configuration for the region we're using and validate only
340
+ # that region.
341
+ config = get_region_config(@region)
342
+
343
+ if !config.use_iam_profile
344
+ errors << I18n.t("vagrant_gq.config.access_key_id_required") if \
345
+ config.access_key_id.nil?
346
+ errors << I18n.t("vagrant_gq.config.secret_access_key_required") if \
347
+ config.secret_access_key.nil?
348
+ end
349
+
350
+ if config.associate_public_ip && !subnet_id
351
+ errors << I18n.t("vagrant_gq.config.subnet_id_required_with_public_ip")
352
+ end
353
+
354
+ errors << I18n.interpolate("vagrant_gq.config.qmi_required", :region => @region) if config.qmi.nil?
355
+ end
356
+
357
+ { "GQ Provider" => errors }
358
+ end
359
+
360
+ # This gets the configuration for a specific region. It shouldn't
361
+ # be called by the general public and is only used internally.
362
+ def get_region_config(name)
363
+ if !@__finalized
364
+ raise "Configuration must be finalized before calling this method."
365
+ end
366
+
367
+ # Return the compiled region config
368
+ @__compiled_region_configs[name] || self
369
+ end
370
+ end
371
+ end
372
+ end
@@ -0,0 +1,31 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module GQ
5
+ module Errors
6
+ class VagrantGQError < Vagrant::Errors::VagrantError
7
+ error_namespace("vagrant_gq.errors")
8
+ end
9
+
10
+ class FogError < VagrantGQError
11
+ error_key(:fog_error)
12
+ end
13
+
14
+ class InternalFogError < VagrantGQError
15
+ error_key(:internal_fog_error)
16
+ end
17
+
18
+ class InstanceReadyTimeout < VagrantGQError
19
+ error_key(:instance_ready_timeout)
20
+ end
21
+
22
+ class RsyncError < VagrantGQError
23
+ error_key(:rsync_error)
24
+ end
25
+
26
+ class MkdirError < VagrantGQError
27
+ error_key(:mkdir_error)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,73 @@
1
+ begin
2
+ require "vagrant"
3
+ rescue LoadError
4
+ raise "The Vagrant GQ plugin must be run within Vagrant."
5
+ end
6
+
7
+ # This is a sanity check to make sure no one is attempting to install
8
+ # this into an early Vagrant version.
9
+ if Vagrant::VERSION < "1.2.0"
10
+ raise "The Vagrant GQ plugin is only compatible with Vagrant 1.2+"
11
+ end
12
+
13
+ module VagrantPlugins
14
+ module GQ
15
+ class Plugin < Vagrant.plugin("2")
16
+ name "GQ"
17
+ description <<-DESC
18
+ This plugin installs a provider that allows Vagrant to manage
19
+ machines in GQ (EC2/VPC).
20
+ DESC
21
+
22
+ config(:gq, :provider) do
23
+ require_relative "config"
24
+ Config
25
+ end
26
+
27
+ provider(:gq, parallel: true) do
28
+ # Setup logging and i18n
29
+ setup_logging
30
+ setup_i18n
31
+
32
+ # Return the provider
33
+ require_relative "provider"
34
+ Provider
35
+ end
36
+
37
+ # This initializes the internationalization strings.
38
+ def self.setup_i18n
39
+ I18n.load_path << File.expand_path("locales/en.yml", GQ.source_root)
40
+ I18n.reload!
41
+ end
42
+
43
+ # This sets up our log level to be whatever VAGRANT_LOG is.
44
+ def self.setup_logging
45
+ require "log4r"
46
+
47
+ level = nil
48
+ begin
49
+ level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
50
+ rescue NameError
51
+ # This means that the logging constant wasn't found,
52
+ # which is fine. We just keep `level` as `nil`. But
53
+ # we tell the user.
54
+ level = nil
55
+ end
56
+
57
+ # Some constants, such as "true" resolve to booleans, so the
58
+ # above error checking doesn't catch it. This will check to make
59
+ # sure that the log level is an integer, as Log4r requires.
60
+ level = nil if !level.is_a?(Integer)
61
+
62
+ # Set the logging level on all "vagrant" namespaced
63
+ # logs as long as we have a valid level.
64
+ if level
65
+ logger = Log4r::Logger.new("vagrant_gq")
66
+ logger.outputters = Log4r::Outputter.stderr
67
+ logger.level = level
68
+ logger = nil
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end