vagrant-brightbox 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. data/.gitignore +15 -0
  2. data/CHANGELOG.md +4 -0
  3. data/Gemfile +10 -0
  4. data/LICENSE +8 -0
  5. data/README.md +217 -0
  6. data/Rakefile +21 -0
  7. data/Vagrantfile.example +105 -0
  8. data/dummy.box +0 -0
  9. data/example_box/README.md +9 -0
  10. data/example_box/metadata.json +3 -0
  11. data/lib/vagrant-brightbox/action/connect_brightbox.rb +53 -0
  12. data/lib/vagrant-brightbox/action/create_server.rb +137 -0
  13. data/lib/vagrant-brightbox/action/delete_server.rb +26 -0
  14. data/lib/vagrant-brightbox/action/forced_halt.rb +27 -0
  15. data/lib/vagrant-brightbox/action/is_created.rb +18 -0
  16. data/lib/vagrant-brightbox/action/is_running.rb +18 -0
  17. data/lib/vagrant-brightbox/action/map_cloud_ip.rb +68 -0
  18. data/lib/vagrant-brightbox/action/message_already_created.rb +16 -0
  19. data/lib/vagrant-brightbox/action/message_not_created.rb +16 -0
  20. data/lib/vagrant-brightbox/action/read_ssh_info.rb +69 -0
  21. data/lib/vagrant-brightbox/action/read_state.rb +38 -0
  22. data/lib/vagrant-brightbox/action/start_server.rb +28 -0
  23. data/lib/vagrant-brightbox/action/sync_folders.rb +58 -0
  24. data/lib/vagrant-brightbox/action/timed_provision.rb +21 -0
  25. data/lib/vagrant-brightbox/action/unsupported.rb +18 -0
  26. data/lib/vagrant-brightbox/action.rb +166 -0
  27. data/lib/vagrant-brightbox/config.rb +268 -0
  28. data/lib/vagrant-brightbox/errors.rb +34 -0
  29. data/lib/vagrant-brightbox/plugin.rb +73 -0
  30. data/lib/vagrant-brightbox/provider.rb +50 -0
  31. data/lib/vagrant-brightbox/util/timer.rb +17 -0
  32. data/lib/vagrant-brightbox/version.rb +5 -0
  33. data/lib/vagrant-brightbox.rb +18 -0
  34. data/locales/en.yml +88 -0
  35. data/spec/vagrant-brightbox/config_spec.rb +179 -0
  36. data/vagrant-brightbox.gemspec +23 -0
  37. metadata +122 -0
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ # OS-specific
2
+ .DS_Store
3
+
4
+ # Bundler/Rubygems
5
+ *.gem
6
+ .bundle
7
+ pkg/*
8
+ tags
9
+ Gemfile.lock
10
+
11
+ # Vagrant
12
+ .vagrant
13
+ Vagrantfile
14
+ manifests/*
15
+ !example_box/Vagrantfile
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ # 0.1.0 (unreleased)
2
+
3
+ * Exclude the ".vagrant" directory from rsync.
4
+ * Initial release.
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ # We depend on Vagrant for development, but we don't add it as a
7
+ # gem dependency because we expect to be installed within the
8
+ # Vagrant environment itself using `vagrant plugin`.
9
+ gem "vagrant", :git => "git://github.com/mitchellh/vagrant.git"
10
+ end
data/LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ The MIT License (MIT)
2
+ Copyright (c) 2013 Mitchell Hashimoto
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5
+
6
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7
+
8
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,217 @@
1
+ # Vagrant Brightbox Provider
2
+
3
+ This is a [Vagrant](http://www.vagrantup.com) 1.1+ plugin that adds a [Brightbox](http://brightbox.com/)
4
+ provider to Vagrant, allowing Vagrant to control and provision servers in
5
+ the Brightbox Cloud
6
+
7
+ **Note:** This plugin requires Vagrant 1.1+,
8
+
9
+ ## Features
10
+
11
+ * Boot Brightbox Cloud servers.
12
+ * SSH into the servers.
13
+ * Provision the servers with any built-in Vagrant provisioner.
14
+ * Minimal synced folder support via `rsync`.
15
+ * Define region-specific configurations so Vagrant can manage servers
16
+ in multiple regions.
17
+
18
+ ## Usage
19
+
20
+ Install using standard Vagrant 1.1+ plugin installation methods. After
21
+ installing, `vagrant up` and specify the `brightbox` provider. An example is
22
+ shown below.
23
+
24
+ ```
25
+ $ vagrant plugin install vagrant-brightbox
26
+ ...
27
+ $ vagrant up --provider=brightbox
28
+ ...
29
+ ```
30
+
31
+ Of course prior to doing this, you'll need to obtain an Brightbox-compatible
32
+ box file for Vagrant.
33
+
34
+ ## Quick Start
35
+
36
+ After installing the plugin (instructions above), the quickest way to get
37
+ started is to actually use a dummy Brightbox box and specify all the details
38
+ manually within a `config.vm.provider` block. So first, add the dummy
39
+ box using any name you want:
40
+
41
+ ```
42
+ $ vagrant box add dummy https://github.com/NeilW/vagrant-brightbox/raw/master/dummy.box
43
+ ...
44
+ ```
45
+
46
+ And then make a Vagrantfile that looks like the following, filling in
47
+ your information where necessary.
48
+
49
+ ```ruby
50
+ Vagrant.configure("2") do |config|
51
+ config.vm.box = "dummy"
52
+
53
+ config.vm.provider :brightbox do |brightbox|
54
+ brightbox.client_id = "YOUR API CLIENT ID"
55
+ brightbox.secret = "YOUR API SECRET"
56
+ brightbox.ssh_private_key_path = "PATH TO YOUR PRIVATE KEY"
57
+
58
+ brightbox.image_id = "img-q6gc8"
59
+ brightbox.ssh_username = "ubuntu"
60
+ end
61
+ end
62
+ ```
63
+
64
+ And then run `vagrant up --provider=brightbox`.
65
+
66
+ This will start an Ubuntu 12.04 server in the gb1 region within
67
+ your account. And assuming your SSH information was filled in properly
68
+ within your Vagrantfile, SSH and provisioning will work as well.
69
+
70
+ Note that normally a lot of this boilerplate is encoded within the box
71
+ file, but the box file used for the quick start, the "dummy" box, has
72
+ no preconfigured defaults.
73
+
74
+ Instead of having to add our client credentials to each Vagrantfile
75
+ we can put them in the Fog configuration file. Create a new
76
+ file at `~/.fog` and add the following:
77
+
78
+ ```
79
+ :default:
80
+ :brightbox_client_id: "your_api_client_id"
81
+ :brightbox_secret: "your_secret"
82
+ ```
83
+
84
+ ## Box Format
85
+
86
+ Every provider in Vagrant must introduce a custom box format. This
87
+ provider introduces `brightbox` boxes. You can view an example box in
88
+ the [example_box/ directory](https://github.com/NeilW/vagrant-brightbox/tree/master/example_box).
89
+ That directory also contains instructions on how to build a box.
90
+
91
+ The box format is basically just the required `metadata.json` file
92
+ along with a `Vagrantfile` that does default settings for the
93
+ provider-specific configuration for this provider.
94
+
95
+ ## Configuration
96
+
97
+ This provider exposes quite a few provider-specific configuration options:
98
+
99
+ * `client_id` - The api access key for accessing Brightbox in the form 'cli-xxxxx'
100
+ * `secret` - The api secret access code for accessing Brightbox
101
+ * `image_id` - The image id to boot, in the form 'img-xxxxx'
102
+ * `zone` - The zone within the region to launch
103
+ the server. If nil, it will use the default for this account.
104
+ * `server_type` - The type of server, such as "nano"
105
+ * `region` - The region to start the server in, such as "gb1"
106
+ * `ssh_private_key_path` - The path to the SSH private key. This overrides
107
+ `config.ssh.private_key_path`.
108
+ * `ssh_username` - The SSH username, which overrides `config.ssh.username`.
109
+ * `security_groups` - An array of security groups for the server.
110
+
111
+ If you are the collaborator on a number of accounts you can specify which one you want by setting the following options:
112
+
113
+ * `username` - User id in the form 'usr-xxxxx'
114
+ * `password` - The password for the user id
115
+ * `account` - Create servers in the context of this account - in the form 'acc-xxxxx'
116
+
117
+ These can be set like typical provider-specific configuration:
118
+
119
+ ```ruby
120
+ Vagrant.configure("2") do |config|
121
+ # ... other stuff
122
+
123
+ config.vm.provider :brightbox do |brightbox|
124
+ brightbox.client_id = "cli-fooxx"
125
+ brightbox.secret = "barfoobarfoobar"
126
+ end
127
+ end
128
+ ```
129
+
130
+ In addition to the above top-level configs, you can use the `region_config`
131
+ method to specify region-specific overrides within your Vagrantfile. Note
132
+ that the top-level `region` config must always be specified to choose which
133
+ region you want to actually use, however. This looks like this:
134
+
135
+ ```ruby
136
+ Vagrant.configure("2") do |config|
137
+ # ... other stuff
138
+
139
+ config.vm.provider :brightbox do |brightbox|
140
+ brightbox.client_id = "foo"
141
+ brightbox.secret = "bar"
142
+ brightbox.region = "gb1"
143
+
144
+ # Simply region config
145
+ brightbox.region_config "gb1", :image_id => "img-mvunm"
146
+
147
+ # More comprehensive region config
148
+ brightbox.region_config "gb1" do |region|
149
+ region.image_id = "img-mvunm"
150
+ end
151
+ end
152
+ end
153
+ ```
154
+
155
+ The region-specific configurations will override the top-level
156
+ configurations when that region is used. They otherwise inherit
157
+ the top-level configurations, as you would probably expect.
158
+
159
+ ## Networks
160
+
161
+ By default each brightbox is created and mapped to a cloud ip so that
162
+ you can access it over the public network.
163
+
164
+ However this can exhaust your allocation of cloud ips if you have several servers. Therefore a couple of networking options are supported.
165
+
166
+ ```ruby
167
+ # Switch off cloud ip mapping and access servers over the IPv4 private
168
+ # network - useful if you are running Vagrant from another cloud server.
169
+ config.vm.network :private_network
170
+
171
+ # Switch off cloud ip mapping and access servers over IPv6.
172
+ config.vm.network :public_network, ipv6: true
173
+ ```
174
+
175
+ ## Synced Folders
176
+
177
+ There is minimal support for synced folders. Upon `vagrant up`,
178
+ `vagrant reload`, and `vagrant provision`, the Brightbox provider will use
179
+ `rsync` (if available) to uni-directionally sync the folder to
180
+ the remote machine over SSH.
181
+
182
+ This is good enough for all built-in Vagrant provisioners (shell,
183
+ chef, and puppet) to work!
184
+
185
+ ## Development
186
+
187
+ To work on the `vagrant-brightbox` plugin, clone this repository out, and use
188
+ [Bundler](http://gembundler.com) to get the dependencies:
189
+
190
+ ```
191
+ $ bundle
192
+ ```
193
+
194
+ Once you have the dependencies, verify the unit tests pass with `rake`:
195
+
196
+ ```
197
+ $ bundle exec rake
198
+ ```
199
+
200
+ If those pass, you're ready to start developing the plugin. You can test
201
+ the plugin without installing it into your Vagrant environment by just
202
+ creating a `Vagrantfile` in the top level of this directory (it is gitignored)
203
+ that uses it:
204
+
205
+ ```ruby
206
+ Vagrant.require_plugin "vagrant-brightbox"
207
+
208
+ Vagrant.configure("2") do |config|
209
+ #Config here
210
+ end
211
+ ```
212
+
213
+ and then use bundler to execute Vagrant:
214
+
215
+ ```
216
+ $ bundle exec vagrant up --provider=brightbox
217
+ ```
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'rspec/core/rake_task'
4
+
5
+ # Immediately sync all stdout so that tools like buildbot can
6
+ # immediately load in the output.
7
+ $stdout.sync = true
8
+ $stderr.sync = true
9
+
10
+ # Change to the directory of this file.
11
+ Dir.chdir(File.expand_path("../", __FILE__))
12
+
13
+ # This installs the tasks that help with gem creation and
14
+ # publishing.
15
+ Bundler::GemHelper.install_tasks
16
+
17
+ # Install the `spec` task so that we can run tests.
18
+ RSpec::Core::RakeTask.new
19
+
20
+ # Default task is to run the unit tests
21
+ task :default => "spec"
@@ -0,0 +1,105 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ Vagrant.require_plugin "vagrant-brightbox"
5
+
6
+ Vagrant.configure("2") do |config|
7
+ config.vm.box = "dummy"
8
+
9
+ config.vm.provider "brightbox" do |brightbox|
10
+ brightbox.client_id = "cli-xxxxx"
11
+ brightbox.secret = "abc123"
12
+ brightbox.ssh_username = "ubuntu"
13
+ brightbox.ssh_private_key_path = "/home/here/.ssh/id_rsa"
14
+ brightbox.image_id = "img-77j4h"
15
+ #brightbox.auth_url = "https://api.gb1.brightbox.com"
16
+ #brightbox.api_url = brightbox.auth_url
17
+ #brightbox.region = "gb1"
18
+ end
19
+
20
+ # By default the Brightbox provider maps a cloud ip to each server
21
+ # created and accesses the server over the public IPv4 network. This
22
+ # may cause your allocation to be exhausted. Therefore there are a couple
23
+ # of options.
24
+ #
25
+ # Switch off cloud ip allocation and access over the private IPv4
26
+ # network. Useful if Vagrant is running on another cloud server in the
27
+ # same region.
28
+ #
29
+ # config.vm.network :private_network
30
+ #
31
+ # Switch off cloud ip allocation and access over the public IPv6 network
32
+ #
33
+ # config.vm.network :public_network, ipv6: true
34
+
35
+ config.vm.provision :shell do |s|
36
+ s.inline=<<-END
37
+ apt-get install -y -V puppet
38
+ END
39
+ end
40
+
41
+
42
+ # Enable provisioning with Puppet stand alone. Puppet manifests
43
+ # are contained in a directory path relative to this Vagrantfile.
44
+ # You will need to create the manifests directory and a manifest in
45
+ # the file base.pp in the manifests_path directory.
46
+ #
47
+ # An example Puppet manifest to provision the message of the day:
48
+ #
49
+ # # group { "puppet":
50
+ # # ensure => "present",
51
+ # # }
52
+ # #
53
+ # # File { owner => 0, group => 0, mode => 0644 }
54
+ # #
55
+ # # file { '/etc/motd':
56
+ # # content => "Welcome to your Vagrant-built virtual machine!
57
+ # # Managed by Puppet.\n"
58
+ # # }
59
+ #
60
+ # config.vm.provision :puppet do |puppet|
61
+ # puppet.manifests_path = "manifests"
62
+ # puppet.manifest_file = "base.pp"
63
+ # end
64
+
65
+ # Won't work without puppet installed on the image.
66
+ config.vm.provision :puppet
67
+
68
+ # Enable provisioning with chef solo, specifying a cookbooks path, roles
69
+ # path, and data_bags path (all relative to this Vagrantfile), and adding
70
+ # some recipes and/or roles.
71
+ #
72
+ # config.vm.provision :chef_solo do |chef|
73
+ # chef.cookbooks_path = "../my-recipes/cookbooks"
74
+ # chef.roles_path = "../my-recipes/roles"
75
+ # chef.data_bags_path = "../my-recipes/data_bags"
76
+ # chef.add_recipe "mysql"
77
+ # chef.add_role "web"
78
+ #
79
+ # # You may also specify custom JSON attributes:
80
+ # chef.json = { :mysql_password => "foo" }
81
+ # end
82
+
83
+ # Enable provisioning with chef server, specifying the chef server URL,
84
+ # and the path to the validation key (relative to this Vagrantfile).
85
+ #
86
+ # The Opscode Platform uses HTTPS. Substitute your organization for
87
+ # ORGNAME in the URL and validation key.
88
+ #
89
+ # If you have your own Chef Server, use the appropriate URL, which may be
90
+ # HTTP instead of HTTPS depending on your configuration. Also change the
91
+ # validation key to validation.pem.
92
+ #
93
+ # config.vm.provision :chef_client do |chef|
94
+ # chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME"
95
+ # chef.validation_key_path = "ORGNAME-validator.pem"
96
+ # end
97
+ #
98
+ # If you're using the Opscode platform, your validator client is
99
+ # ORGNAME-validator, replacing ORGNAME with your organization name.
100
+ #
101
+ # If you have your own Chef Server, the default validation client name is
102
+ # chef-validator, unless you changed the configuration.
103
+ #
104
+ # chef.validation_client_name = "ORGNAME-validator"
105
+ end
data/dummy.box ADDED
Binary file
@@ -0,0 +1,9 @@
1
+ # Vagrant Brightbox Cloud Example Box
2
+
3
+ Vagrant providers each require a custom provider-specific box format.
4
+ This folder shows the example contents of a box for the `brightbox` provider.
5
+ To turn this into a box:
6
+
7
+ ```
8
+ $ tar cvzf bright.box ./metadata.json
9
+ ```
@@ -0,0 +1,3 @@
1
+ {
2
+ "provider": "brightbox"
3
+ }
@@ -0,0 +1,53 @@
1
+ require "fog"
2
+ require "log4r"
3
+
4
+ module VagrantPlugins
5
+ module Brightbox
6
+ module Action
7
+ # This action connects to Brightbox, verifies credentials work, and
8
+ # puts the Brightbox connection object into the `:brightbox_compute` key
9
+ # in the environment.
10
+ class ConnectBrightbox
11
+ def initialize(app, env)
12
+ @app = app
13
+ @logger = Log4r::Logger.new("vagrant_brightbox::action::connect_brightbox")
14
+ end
15
+
16
+ def call(env)
17
+ # Get the region we're going to booting up in
18
+ region = env[:machine].provider_config.region
19
+
20
+ # Get the configs
21
+ region_config = env[:machine].provider_config.get_region_config(region)
22
+ client_id = region_config.client_id
23
+ client_secret = region_config.secret
24
+ username = region_config.username
25
+ password = region_config.password
26
+ account = region_config.account
27
+ auth_url = region_config.auth_url
28
+ api_url = region_config.api_url
29
+
30
+ @logger.info("Connecting to Brightbox...")
31
+ @logger.info("Fog credentials are: #{Fog.credentials.inspect}")
32
+ fog_options={
33
+ :provider => :brightbox,
34
+ :brightbox_auth_url => auth_url,
35
+ :brightbox_api_url => api_url,
36
+ :brightbox_client_id => client_id,
37
+ :brightbox_secret => client_secret,
38
+ :brightbox_username => username,
39
+ :brightbox_password => password,
40
+ :brightbox_account => account,
41
+ }
42
+ fog_options.delete_if {|k, v| v.nil? }
43
+ @logger.info("Fog compute options are: #{fog_options.inspect}")
44
+ env[:brightbox_compute] = Fog::Compute.new(fog_options)
45
+
46
+ @app.call(env)
47
+ rescue ArgumentError => e
48
+ raise Errors::FogError, :message => e.message
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,137 @@
1
+ require "log4r"
2
+
3
+ require 'vagrant/util/retryable'
4
+
5
+ require 'vagrant-brightbox/util/timer'
6
+
7
+ module VagrantPlugins
8
+ module Brightbox
9
+ module Action
10
+ # This creates the Brightbox Server
11
+ class CreateServer
12
+ include Vagrant::Util::Retryable
13
+
14
+ def initialize(app, env)
15
+ @app = app
16
+ @logger = Log4r::Logger.new("vagrant_brightbox::action::create_server")
17
+ end
18
+
19
+ def call(env)
20
+ # Initialize metrics if they haven't been
21
+ env[:metrics] ||= {}
22
+
23
+ # Get the region we're going to booting up in
24
+ region = env[:machine].provider_config.region
25
+
26
+ # Get the configs
27
+ region_config = env[:machine].provider_config.get_region_config(region)
28
+ image_id = region_config.image_id
29
+ zone = region_config.zone
30
+ server_name = region_config.server_name
31
+ server_type = region_config.server_type
32
+ server_groups = region_config.server_groups
33
+
34
+ # Launch!
35
+ env[:ui].info(I18n.t("vagrant_brightbox.launching_server"))
36
+ env[:ui].info(" -- Type: #{server_type}") if server_type
37
+ env[:ui].info(" -- Image: #{image_id}") if image_id
38
+ env[:ui].info(" -- Region: #{region}")
39
+ env[:ui].info(" -- Name: #{server_name}") if server_name
40
+ env[:ui].info(" -- Zone: #{zone}") if zone
41
+ env[:ui].info(" -- Server Groups: #{server_groups.inspect}") if !server_groups.empty?
42
+
43
+ begin
44
+ options = {
45
+ :image_id => image_id,
46
+ :name => server_name,
47
+ :flavor_id => server_type,
48
+ :zone_id => zone
49
+ }
50
+
51
+ if !server_groups.empty?
52
+ options[:server_groups] = server_groups
53
+ end
54
+
55
+ server = env[:brightbox_compute].servers.create(options)
56
+ rescue Excon::Errors::HTTPStatusError => e
57
+ raise Errors::FogError, :message => e.response
58
+ end
59
+
60
+ # Immediately save the ID since it is created at this point.
61
+ env[:machine].id = server.id
62
+
63
+ # Wait for the server to build
64
+ env[:metrics]["server_build_time"] = Util::Timer.time do
65
+ env[:ui].info(I18n.t("vagrant_brightbox.waiting_for_build"))
66
+ retryable(:on => Fog::Errors::TimeoutError, :tries => 30) do
67
+ # If we're interrupted don't worry about waiting
68
+ next if env[:interrupted]
69
+
70
+ # Wait for the server to be ready
71
+ server.wait_for(2) { ready? }
72
+ end
73
+ end
74
+
75
+ @logger.info("Time for server to build: #{env[:metrics]["server_build_time"]}")
76
+
77
+ if !env[:interrupted]
78
+ @app.call(env)
79
+ env[:metrics]["instance_ssh_time"] = Util::Timer.time do
80
+ # Wait for SSH to be ready.
81
+ env[:ui].info(I18n.t("vagrant_brightbox.waiting_for_ssh"))
82
+ while true
83
+ # If we're interrupted then just back out
84
+ break if env[:interrupted]
85
+ break if ready?(env[:machine])
86
+ sleep 2
87
+ end
88
+ end
89
+
90
+ @logger.info("Time for SSH ready: #{env[:metrics]["instance_ssh_time"]}")
91
+
92
+ # Ready and booted!
93
+ env[:ui].info(I18n.t("vagrant_brightbox.ready"))
94
+ end
95
+
96
+ # Terminate the instance if we were interrupted
97
+ terminate(env) if env[:interrupted]
98
+
99
+ end
100
+
101
+ # Check if machine is ready, trapping only non-fatal errors
102
+ def ready?(machine)
103
+ @logger.info("Checking if SSH is ready or is permanently broken...")
104
+ @logger.info("Connecting as '#{machine.ssh_info[:username]}'") if machine.ssh_info[:username]
105
+ # Yes this is cheating.
106
+ machine.communicate.send(:connect)
107
+ @logger.info("SSH is ready")
108
+ true
109
+ # Fatal errors
110
+ rescue Vagrant::Errors::SSHAuthenticationFailed
111
+ raise
112
+ # Transient errors
113
+ rescue Vagrant::Errors::VagrantError => e
114
+ @logger.info("SSH not up: #{e.inspect}")
115
+ return false
116
+ end
117
+
118
+ def recover(env)
119
+ return if env["vagrant.error"].is_a?(Vagrant::Errors::VagrantError)
120
+
121
+ if env[:machine].provider.state.id != :not_created
122
+ # Undo the import
123
+ terminate(env)
124
+ end
125
+ end
126
+
127
+ def terminate(env)
128
+ destroy_env = env.dup
129
+ destroy_env.delete(:interrupted)
130
+ destroy_env[:config_validate] = false
131
+ destroy_env[:force_confirm_destroy] = true
132
+ env[:action_runner].run(Action.action_destroy, destroy_env)
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,26 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module Brightbox
5
+ module Action
6
+ # This terminates the running server
7
+ class DeleteServer
8
+ def initialize(app, env)
9
+ @app = app
10
+ @logger = Log4r::Logger.new("vagrant_brightbox::action::delete_server")
11
+ end
12
+
13
+ def call(env)
14
+ server = env[:brightbox_compute].servers.get(env[:machine].id)
15
+
16
+ # Destroy the server and remove the tracking ID
17
+ env[:ui].info(I18n.t("vagrant_brightbox.deleting_server"))
18
+ server.destroy
19
+ env[:machine].id = nil
20
+
21
+ @app.call(env)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module Brightbox
5
+ module Action
6
+ # This halts the running server via the api
7
+ class ForcedHalt
8
+ def initialize(app, env)
9
+ @app = app
10
+ @logger = Log4r::Logger.new("vagrant_brightbox::action::forced_halt")
11
+ end
12
+
13
+ def call(env)
14
+ server = env[:brightbox_compute].servers.get(env[:machine].id)
15
+
16
+ if server.ready?
17
+ # Stop the server.
18
+ env[:ui].info(I18n.t("vagrant_brightbox.stopping_server"))
19
+ server.stop
20
+ end
21
+
22
+ @app.call(env)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,18 @@
1
+ module VagrantPlugins
2
+ module Brightbox
3
+ module Action
4
+ # This can be used with "Call" built-in to check if the machine
5
+ # is created and branch in the middleware.
6
+ class IsCreated
7
+ def initialize(app, env)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ env[:result] = env[:machine].state.id != :not_created
13
+ @app.call(env)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module VagrantPlugins
2
+ module Brightbox
3
+ module Action
4
+ # This can be used with "Call" built-in to check if the machine
5
+ # is active and branch in the middleware.
6
+ class IsRunning
7
+ def initialize(app, env)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ env[:result] = env[:machine].state.id == :active
13
+ @app.call(env)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end