vagrant-gq 0.1.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.
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,247 @@
1
+ require "log4r"
2
+ require 'json'
3
+
4
+ require 'vagrant/util/retryable'
5
+
6
+ require 'vagrant-gq/util/timer'
7
+
8
+ module VagrantPlugins
9
+ module GQ
10
+ module Action
11
+ # This runs the configured instance.
12
+ class RunInstance
13
+ include Vagrant::Util::Retryable
14
+
15
+ def initialize(app, env)
16
+ @app = app
17
+ @logger = Log4r::Logger.new("vagrant_gq::action::run_instance")
18
+ end
19
+
20
+ def call(env)
21
+ # Initialize metrics if they haven't been
22
+ env[:metrics] ||= {}
23
+
24
+ # Get the region we're going to booting up in
25
+ region = env[:machine].provider_config.region
26
+
27
+ # Get the configs
28
+ region_config = env[:machine].provider_config.get_region_config(region)
29
+ ami = region_config.qmi
30
+ availability_zone = region_config.availability_zone
31
+ instance_type = region_config.instance_type
32
+ keypair = region_config.keypair_name
33
+ private_ip_address = region_config.private_ip_address
34
+ security_groups = region_config.security_groups
35
+ subnet_id = region_config.subnet_id
36
+ tags = region_config.tags
37
+ user_data = region_config.user_data
38
+ block_device_mapping = region_config.block_device_mapping
39
+ elastic_ip = region_config.elastic_ip
40
+ terminate_on_shutdown = region_config.terminate_on_shutdown
41
+ iam_instance_profile_arn = region_config.iam_instance_profile_arn
42
+ iam_instance_profile_name = region_config.iam_instance_profile_name
43
+ monitoring = region_config.monitoring
44
+ ebs_optimized = region_config.ebs_optimized
45
+ associate_public_ip = region_config.associate_public_ip
46
+
47
+ # If there is no keypair then warn the user
48
+ if !keypair
49
+ env[:ui].warn(I18n.t("vagrant_gq.launch_no_keypair"))
50
+ end
51
+
52
+ # If there is a subnet ID then warn the user
53
+ if subnet_id && !elastic_ip
54
+ env[:ui].warn(I18n.t("vagrant_gq.launch_vpc_warning"))
55
+ end
56
+
57
+ # Launch!
58
+ env[:ui].info(I18n.t("vagrant_gq.launching_instance"))
59
+ env[:ui].info(" -- Type: #{instance_type}")
60
+ env[:ui].info(" -- AMI: #{ami}")
61
+ env[:ui].info(" -- Region: #{region}")
62
+ env[:ui].info(" -- Availability Zone: #{availability_zone}") if availability_zone
63
+ env[:ui].info(" -- Keypair: #{keypair}") if keypair
64
+ env[:ui].info(" -- Subnet ID: #{subnet_id}") if subnet_id
65
+ env[:ui].info(" -- IAM Instance Profile ARN: #{iam_instance_profile_arn}") if iam_instance_profile_arn
66
+ env[:ui].info(" -- IAM Instance Profile Name: #{iam_instance_profile_name}") if iam_instance_profile_name
67
+ env[:ui].info(" -- Private IP: #{private_ip_address}") if private_ip_address
68
+ env[:ui].info(" -- Elastic IP: #{elastic_ip}") if elastic_ip
69
+ env[:ui].info(" -- User Data: yes") if user_data
70
+ env[:ui].info(" -- Security Groups: #{security_groups.inspect}") if !security_groups.empty?
71
+ env[:ui].info(" -- User Data: #{user_data}") if user_data
72
+ env[:ui].info(" -- Block Device Mapping: #{block_device_mapping}") if block_device_mapping
73
+ env[:ui].info(" -- Terminate On Shutdown: #{terminate_on_shutdown}")
74
+ env[:ui].info(" -- Monitoring: #{monitoring}")
75
+ env[:ui].info(" -- EBS optimized: #{ebs_optimized}")
76
+ env[:ui].info(" -- Assigning a public IP address in a VPC: #{associate_public_ip}")
77
+
78
+ options = {
79
+ :availability_zone => availability_zone,
80
+ :flavor_id => instance_type,
81
+ :image_id => ami,
82
+ :key_name => keypair,
83
+ :private_ip_address => private_ip_address,
84
+ :subnet_id => subnet_id,
85
+ :iam_instance_profile_arn => iam_instance_profile_arn,
86
+ :iam_instance_profile_name => iam_instance_profile_name,
87
+ :tags => tags,
88
+ :user_data => user_data,
89
+ :block_device_mapping => block_device_mapping,
90
+ :instance_initiated_shutdown_behavior => terminate_on_shutdown == true ? "terminate" : nil,
91
+ :monitoring => monitoring,
92
+ :ebs_optimized => ebs_optimized,
93
+ :associate_public_ip => associate_public_ip
94
+ }
95
+ if !security_groups.empty?
96
+ security_group_key = options[:subnet_id].nil? ? :groups : :security_group_ids
97
+ options[security_group_key] = security_groups
98
+ end
99
+
100
+ begin
101
+ env[:ui].warn(I18n.t("vagrant_gq.warn_ssh_access")) unless allows_ssh_port?(env, security_groups, subnet_id)
102
+
103
+ server = env[:gq_compute].servers.create(options)
104
+ rescue Fog::Compute::GQ::NotFound => e
105
+ # Invalid subnet doesn't have its own error so we catch and
106
+ # check the error message here.
107
+ if e.message =~ /subnet ID/
108
+ raise Errors::FogError,
109
+ :message => "Subnet ID not found: #{subnet_id}"
110
+ end
111
+
112
+ raise
113
+ rescue Fog::Compute::GQ::Error => e
114
+ raise Errors::FogError, :message => e.message
115
+ rescue Excon::Errors::HTTPStatusError => e
116
+ raise Errors::InternalFogError,
117
+ :error => e.message,
118
+ :response => e.response.body
119
+ end
120
+
121
+ # Immediately save the ID since it is created at this point.
122
+ env[:machine].id = server.id
123
+
124
+ # Wait for the instance to be ready first
125
+ env[:metrics]["instance_ready_time"] = Util::Timer.time do
126
+ tries = region_config.instance_ready_timeout / 2
127
+
128
+ env[:ui].info(I18n.t("vagrant_gq.waiting_for_ready"))
129
+ begin
130
+ retryable(:on => Fog::Errors::TimeoutError, :tries => tries) do
131
+ # If we're interrupted don't worry about waiting
132
+ next if env[:interrupted]
133
+
134
+ # Wait for the server to be ready
135
+ server.wait_for(2) { ready? }
136
+ end
137
+ rescue Fog::Errors::TimeoutError
138
+ # Delete the instance
139
+ terminate(env)
140
+
141
+ # Notify the user
142
+ raise Errors::InstanceReadyTimeout,
143
+ timeout: region_config.instance_ready_timeout
144
+ end
145
+ end
146
+
147
+ @logger.info("Time to instance ready: #{env[:metrics]["instance_ready_time"]}")
148
+
149
+ # Allocate and associate an elastic IP if requested
150
+ if elastic_ip
151
+ domain = subnet_id ? 'vpc' : 'standard'
152
+ do_elastic_ip(env, domain, server)
153
+ end
154
+
155
+ if !env[:interrupted]
156
+ env[:metrics]["instance_ssh_time"] = Util::Timer.time do
157
+ # Wait for SSH to be ready.
158
+ env[:ui].info(I18n.t("vagrant_gq.waiting_for_ssh"))
159
+ while true
160
+ # If we're interrupted then just back out
161
+ break if env[:interrupted]
162
+ break if env[:machine].communicate.ready?
163
+ sleep 2
164
+ end
165
+ end
166
+
167
+ @logger.info("Time for SSH ready: #{env[:metrics]["instance_ssh_time"]}")
168
+
169
+ # Ready and booted!
170
+ env[:ui].info(I18n.t("vagrant_gq.ready"))
171
+ end
172
+
173
+ # Terminate the instance if we were interrupted
174
+ terminate(env) if env[:interrupted]
175
+
176
+ @app.call(env)
177
+ end
178
+
179
+ def recover(env)
180
+ return if env["vagrant.error"].is_a?(Vagrant::Errors::VagrantError)
181
+
182
+ if env[:machine].provider.state.id != :not_created
183
+ # Undo the import
184
+ terminate(env)
185
+ end
186
+ end
187
+
188
+ def allows_ssh_port?(env, test_sec_groups, is_vpc)
189
+ port = 22 # TODO get ssh_info port
190
+ test_sec_groups = [ "default" ] if test_sec_groups.empty? # GQ default security group
191
+ # filter groups by name or group_id (vpc)
192
+ groups = test_sec_groups.map do |tsg|
193
+ env[:gq_compute].security_groups.all.select { |sg| tsg == (is_vpc ? sg.group_id : sg.name) }
194
+ end.flatten
195
+ # filter TCP rules
196
+ rules = groups.map { |sg| sg.ip_permissions.select { |r| r["ipProtocol"] == "tcp" } }.flatten
197
+ # test if any range includes port
198
+ !rules.select { |r| (r["fromPort"]..r["toPort"]).include?(port) }.empty?
199
+ end
200
+
201
+ def do_elastic_ip(env, domain, server)
202
+ begin
203
+ allocation = env[:gq_compute].allocate_address(domain)
204
+ rescue
205
+ @logger.debug("Could not allocate Elastic IP.")
206
+ terminate(env)
207
+ raise Errors::FogError,
208
+ :message => "Could not allocate Elastic IP."
209
+ end
210
+ @logger.debug("Public IP #{allocation.body['publicIp']}")
211
+
212
+ # Associate the address and save the metadata to a hash
213
+ if domain == 'vpc'
214
+ # VPC requires an allocation ID to assign an IP
215
+ association = env[:gq_compute].associate_address(server.id, nil, nil, allocation.body['allocationId'])
216
+ h = { :allocation_id => allocation.body['allocationId'], :association_id => association.body['associationId'], :public_ip => allocation.body['publicIp'] }
217
+ else
218
+ # Standard EC2 instances only need the allocated IP address
219
+ association = env[:gq_compute].associate_address(server.id, allocation.body['publicIp'])
220
+ h = { :public_ip => allocation.body['publicIp'] }
221
+ end
222
+
223
+ unless association.body['return']
224
+ @logger.debug("Could not associate Elastic IP.")
225
+ terminate(env)
226
+ raise Errors::FogError,
227
+ :message => "Could not allocate Elastic IP."
228
+ end
229
+
230
+ # Save this IP to the data dir so it can be released when the instance is destroyed
231
+ ip_file = env[:machine].data_dir.join('elastic_ip')
232
+ ip_file.open('w+') do |f|
233
+ f.write(h.to_json)
234
+ end
235
+ end
236
+
237
+ def terminate(env)
238
+ destroy_env = env.dup
239
+ destroy_env.delete(:interrupted)
240
+ destroy_env[:config_validate] = false
241
+ destroy_env[:force_confirm_destroy] = true
242
+ env[:action_runner].run(Action.action_destroy, destroy_env)
243
+ end
244
+ end
245
+ end
246
+ end
247
+ end
@@ -0,0 +1,81 @@
1
+ require "log4r"
2
+
3
+ require 'vagrant/util/retryable'
4
+
5
+ require 'vagrant-gq/util/timer'
6
+
7
+ module VagrantPlugins
8
+ module GQ
9
+ module Action
10
+ # This starts a stopped instance.
11
+ class StartInstance
12
+ include Vagrant::Util::Retryable
13
+
14
+ def initialize(app, env)
15
+ @app = app
16
+ @logger = Log4r::Logger.new("vagrant_gq::action::start_instance")
17
+ end
18
+
19
+ def call(env)
20
+ # Initialize metrics if they haven't been
21
+ env[:metrics] ||= {}
22
+
23
+ server = env[:gq_compute].servers.get(env[:machine].id)
24
+
25
+ env[:ui].info(I18n.t("vagrant_gq.starting"))
26
+
27
+ begin
28
+ server.start
29
+
30
+ region = env[:machine].provider_config.region
31
+ region_config = env[:machine].provider_config.get_region_config(region)
32
+
33
+ # Wait for the instance to be ready first
34
+ env[:metrics]["instance_ready_time"] = Util::Timer.time do
35
+ tries = region_config.instance_ready_timeout / 2
36
+
37
+ env[:ui].info(I18n.t("vagrant_gq.waiting_for_ready"))
38
+ begin
39
+ retryable(:on => Fog::Errors::TimeoutError, :tries => tries) do
40
+ # If we're interrupted don't worry about waiting
41
+ next if env[:interrupted]
42
+
43
+ # Wait for the server to be ready
44
+ server.wait_for(2) { ready? }
45
+ end
46
+ rescue Fog::Errors::TimeoutError
47
+ # Notify the user
48
+ raise Errors::InstanceReadyTimeout,
49
+ timeout: region_config.instance_ready_timeout
50
+ end
51
+ end
52
+ rescue Fog::Compute::GQ::Error => e
53
+ raise Errors::FogError, :message => e.message
54
+ end
55
+
56
+ @logger.info("Time to instance ready: #{env[:metrics]["instance_ready_time"]}")
57
+
58
+ if !env[:interrupted]
59
+ env[:metrics]["instance_ssh_time"] = Util::Timer.time do
60
+ # Wait for SSH to be ready.
61
+ env[:ui].info(I18n.t("vagrant_gq.waiting_for_ssh"))
62
+ while true
63
+ # If we're interrupted then just back out
64
+ break if env[:interrupted]
65
+ break if env[:machine].communicate.ready?
66
+ sleep 2
67
+ end
68
+ end
69
+
70
+ @logger.info("Time for SSH ready: #{env[:metrics]["instance_ssh_time"]}")
71
+
72
+ # Ready and booted!
73
+ env[:ui].info(I18n.t("vagrant_gq.ready"))
74
+ end
75
+
76
+ @app.call(env)
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,28 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module GQ
5
+ module Action
6
+ # This stops the running instance.
7
+ class StopInstance
8
+ def initialize(app, env)
9
+ @app = app
10
+ @logger = Log4r::Logger.new("vagrant_gq::action::stop_instance")
11
+ end
12
+
13
+ def call(env)
14
+ server = env[:gq_compute].servers.get(env[:machine].id)
15
+
16
+ if env[:machine].state.id == :stopped
17
+ env[:ui].info(I18n.t("vagrant_gq.already_status", :status => env[:machine].state.id))
18
+ else
19
+ env[:ui].info(I18n.t("vagrant_gq.stopping"))
20
+ server.stop(!!env[:force_halt])
21
+ end
22
+
23
+ @app.call(env)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,118 @@
1
+ require "log4r"
2
+
3
+ require "vagrant/util/subprocess"
4
+
5
+ require "vagrant/util/scoped_hash_override"
6
+
7
+ require "vagrant/util/which"
8
+
9
+ module VagrantPlugins
10
+ module GQ
11
+ module Action
12
+ # This middleware uses `rsync` to sync the folders over to the
13
+ # GQ instance.
14
+ class SyncFolders
15
+ include Vagrant::Util::ScopedHashOverride
16
+
17
+ def initialize(app, env)
18
+ @app = app
19
+ @logger = Log4r::Logger.new("vagrant_gq::action::sync_folders")
20
+ end
21
+
22
+ def call(env)
23
+ @app.call(env)
24
+
25
+ ssh_info = env[:machine].ssh_info
26
+
27
+ unless Vagrant::Util::Which.which('rsync')
28
+ env[:ui].warn(I18n.t('vagrant_gq.rsync_not_found_warning', :side => "host"))
29
+ return
30
+ end
31
+
32
+ if env[:machine].communicate.execute('which rsync', :error_check => false) != 0
33
+ env[:ui].warn(I18n.t('vagrant_gq.rsync_not_found_warning', :side => "guest"))
34
+ return
35
+ end
36
+
37
+ env[:machine].config.vm.synced_folders.each do |id, data|
38
+ data = scoped_hash_override(data, :gq)
39
+
40
+ # Ignore disabled shared folders
41
+ next if data[:disabled]
42
+
43
+ hostpath = File.expand_path(data[:hostpath], env[:root_path])
44
+ guestpath = data[:guestpath]
45
+
46
+ # Make sure there is a trailing slash on the host path to
47
+ # avoid creating an additional directory with rsync
48
+ hostpath = "#{hostpath}/" if hostpath !~ /\/$/
49
+
50
+ # on windows rsync.exe requires cygdrive-style paths
51
+ if Vagrant::Util::Platform.windows?
52
+ hostpath = hostpath.gsub(/^(\w):/) { "/cygdrive/#{$1}" }
53
+ end
54
+
55
+ env[:ui].info(I18n.t("vagrant_gq.rsync_folder",
56
+ :hostpath => hostpath,
57
+ :guestpath => guestpath))
58
+
59
+ # Create the host path if it doesn't exist and option flag is set
60
+ if data[:create]
61
+ begin
62
+ FileUtils::mkdir_p(hostpath)
63
+ rescue => err
64
+ raise Errors::MkdirError,
65
+ :hostpath => hostpath,
66
+ :err => err
67
+ end
68
+ end
69
+
70
+ # Create the guest path
71
+ env[:machine].communicate.sudo("mkdir -p '#{guestpath}'")
72
+ env[:machine].communicate.sudo(
73
+ "chown -R #{ssh_info[:username]} '#{guestpath}'")
74
+
75
+ #collect rsync excludes specified :rsync_excludes=>['path1',...] in synced_folder options
76
+ excludes = ['.vagrant/', 'Vagrantfile', *Array(data[:rsync_excludes])].uniq
77
+
78
+ ssh_options = ["StrictHostKeyChecking=no"]
79
+ # Use proxy command if it's set
80
+ if ssh_info[:proxy_command]
81
+ ssh_options.push("ProxyCommand #{ssh_info[:proxy_command]}")
82
+ end
83
+
84
+ # Rsync over to the guest path using the SSH info
85
+ command = [
86
+ "rsync", "--verbose", "--archive", "-z",
87
+ *excludes.map{|e|['--exclude', e]}.flatten,
88
+ "-e", "ssh -p #{ssh_info[:port]} #{ssh_key_options(ssh_info)} " +
89
+ ssh_options.map { |ssh_option| "-o '#{ssh_option}' " }.join,
90
+ hostpath,
91
+ "#{ssh_info[:username]}@#{ssh_info[:host]}:#{guestpath}"]
92
+
93
+ # we need to fix permissions when using rsync.exe on windows, see
94
+ # http://stackoverflow.com/questions/5798807/rsync-permission-denied-created-directories-have-no-permissions
95
+ if Vagrant::Util::Platform.windows?
96
+ command.insert(1, "--chmod", "ugo=rwX")
97
+ end
98
+
99
+ r = Vagrant::Util::Subprocess.execute(*command)
100
+ if r.exit_code != 0
101
+ raise Errors::RsyncError,
102
+ :guestpath => guestpath,
103
+ :hostpath => hostpath,
104
+ :stderr => r.stderr
105
+ end
106
+ end
107
+ end
108
+
109
+ private
110
+
111
+ def ssh_key_options(ssh_info)
112
+ # Ensure that `private_key_path` is an Array (for Vagrant < 1.4)
113
+ Array(ssh_info[:private_key_path]).map { |path| "-i '#{path}' " }.join
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,47 @@
1
+ require "log4r"
2
+ require "json"
3
+
4
+ module VagrantPlugins
5
+ module GQ
6
+ module Action
7
+ # This terminates the running instance.
8
+ class TerminateInstance
9
+ def initialize(app, env)
10
+ @app = app
11
+ @logger = Log4r::Logger.new("vagrant_gq::action::terminate_instance")
12
+ end
13
+
14
+ def call(env)
15
+ server = env[:gq_compute].servers.get(env[:machine].id)
16
+
17
+ # Release the elastic IP
18
+ ip_file = env[:machine].data_dir.join('elastic_ip')
19
+ if ip_file.file?
20
+ release_address(env,ip_file.read)
21
+ ip_file.delete
22
+ end
23
+
24
+ # Destroy the server and remove the tracking ID
25
+ env[:ui].info(I18n.t("vagrant_gq.terminating"))
26
+ server.destroy
27
+ env[:machine].id = nil
28
+
29
+ @app.call(env)
30
+ end
31
+
32
+ # Release an elastic IP address
33
+ def release_address(env,eip)
34
+ h = JSON.parse(eip)
35
+ # Use association_id and allocation_id for VPC, use public IP for EC2
36
+ if h['association_id']
37
+ env[:gq_compute].disassociate_address(nil,h['association_id'])
38
+ env[:gq_compute].release_address(h['allocation_id'])
39
+ else
40
+ env[:gq_compute].disassociate_address(h['public_ip'])
41
+ env[:gq_compute].release_address(h['public_ip'])
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,21 @@
1
+ require "vagrant-gq/util/timer"
2
+
3
+ module VagrantPlugins
4
+ module GQ
5
+ module Action
6
+ # This is the same as the builtin provision except it times the
7
+ # provisioner runs.
8
+ class TimedProvision < Vagrant::Action::Builtin::Provision
9
+ def run_provisioner(env, name, p)
10
+ timer = Util::Timer.time do
11
+ super
12
+ end
13
+
14
+ env[:metrics] ||= {}
15
+ env[:metrics]["provisioner_times"] ||= []
16
+ env[:metrics]["provisioner_times"] << [name, timer]
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,41 @@
1
+ require "log4r"
2
+ require "timeout"
3
+
4
+ module VagrantPlugins
5
+ module GQ
6
+ module Action
7
+ # This action will wait for a machine to reach a specific state or quit by timeout
8
+ class WaitForState
9
+ # env[:result] will be false in case of timeout.
10
+ # @param [Symbol] state Target machine state.
11
+ # @param [Number] timeout Timeout in seconds.
12
+ def initialize(app, env, state, timeout)
13
+ @app = app
14
+ @logger = Log4r::Logger.new("vagrant_gq::action::wait_for_state")
15
+ @state = state
16
+ @timeout = timeout
17
+ end
18
+
19
+ def call(env)
20
+ env[:result] = true
21
+ if env[:machine].state.id == @state
22
+ @logger.info(I18n.t("vagrant_gq.already_status", :status => @state))
23
+ else
24
+ @logger.info("Waiting for machine to reach state #{@state}")
25
+ begin
26
+ Timeout.timeout(@timeout) do
27
+ until env[:machine].state.id == @state
28
+ sleep 2
29
+ end
30
+ end
31
+ rescue Timeout::Error
32
+ env[:result] = false # couldn't reach state in time
33
+ end
34
+ end
35
+
36
+ @app.call(env)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,19 @@
1
+ module VagrantPlugins
2
+ module GQ
3
+ module Action
4
+ class WarnNetworks
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ if env[:machine].config.vm.networks.length > 0
11
+ env[:ui].warn(I18n.t("vagrant_gq.warn_networks"))
12
+ end
13
+
14
+ @app.call(env)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end