vagrant-digitalocean 0.0.3 → 0.0.4
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.
- data/README.md +33 -13
- data/bin/build.sh +6 -0
- data/bin/test_run.sh +3 -0
- data/box/Vagrantfile +1 -1
- data/lib/vagrant-digitalocean.rb +0 -7
- data/lib/vagrant-digitalocean/action.rb +56 -28
- data/lib/vagrant-digitalocean/actions/check_ssh_user.rb +46 -0
- data/lib/vagrant-digitalocean/actions/create.rb +4 -48
- data/lib/vagrant-digitalocean/actions/destroy.rb +6 -21
- data/lib/vagrant-digitalocean/actions/is_active.rb +16 -0
- data/lib/vagrant-digitalocean/actions/message_is_active.rb +18 -0
- data/lib/vagrant-digitalocean/actions/modify_provision_path.rb +40 -0
- data/lib/vagrant-digitalocean/actions/rebuild.rb +36 -0
- data/lib/vagrant-digitalocean/actions/setup_ssh_key.rb +60 -0
- data/lib/vagrant-digitalocean/actions/sync_folders.rb +56 -0
- data/lib/vagrant-digitalocean/commands/rebuild.rb +24 -0
- data/lib/vagrant-digitalocean/config.rb +34 -19
- data/lib/vagrant-digitalocean/errors.rb +8 -0
- data/lib/vagrant-digitalocean/helpers/client.rb +21 -4
- data/lib/vagrant-digitalocean/helpers/translator.rb +1 -1
- data/lib/vagrant-digitalocean/plugin.rb +5 -0
- data/lib/vagrant-digitalocean/provider.rb +4 -9
- data/lib/vagrant-digitalocean/version.rb +2 -2
- data/locales/en.yml +32 -14
- data/test/Vagrantfile.centos +1 -0
- data/test/Vagrantfile.ubuntu +3 -2
- data/test/scripts/setup_user.sh +18 -0
- data/vagrant-digitalocean.gemspec +1 -2
- metadata +13 -6
- data/lib/vagrant-digitalocean/actions/setup_nfs.rb +0 -61
data/README.md
CHANGED
@@ -1,33 +1,47 @@
|
|
1
1
|
# Vagrant Digital Ocean
|
2
2
|
|
3
|
-
`vagrant-digitalocean` is a provider plugin for Vagrant that allows the
|
3
|
+
`vagrant-digitalocean` is a provider plugin for Vagrant that allows the
|
4
|
+
management of [Digital Ocean](https://www.digitalocean.com/) droplets
|
5
|
+
(instances).
|
4
6
|
|
5
|
-
## SSH
|
7
|
+
## SSH Authentication
|
6
8
|
|
7
|
-
|
9
|
+
This provider does not support the use of Vagrant's insecure key for SSH
|
10
|
+
access. You must specify your own SSH key. The key may be defined within
|
11
|
+
the global config section, `config.ssh.private_key_path`, or within the
|
12
|
+
provider config section, `provider.ssh_private_key_path`. The provider
|
13
|
+
config will take precedence. Additionally, you may provide a name for
|
14
|
+
the SSH key using the `ssh_key_name` attribute within the provider config
|
15
|
+
section. This is useful for de-conflict SSH keys used by different
|
16
|
+
individuals when creating machines on Digital Ocean.
|
8
17
|
|
9
18
|
```ruby
|
10
19
|
config.vm.provider :digital_ocean do |provider|
|
11
20
|
provider.ssh_key_name = "My Laptop"
|
12
|
-
provider.
|
21
|
+
provider.ssh_private_key_path = "~/.ssh/id_rsa.pub"
|
13
22
|
|
14
23
|
# additional configuration here
|
15
24
|
end
|
16
25
|
```
|
17
26
|
|
18
|
-
The provider will assume the
|
27
|
+
The provider will assume the public key path is identical to the private
|
28
|
+
key path with the *.pub* extention.
|
19
29
|
|
20
|
-
|
21
|
-
|
22
|
-
|
30
|
+
By default, the provider uses the `root` account for SSH access. This is
|
31
|
+
required for initial droplet creation and provisioning. You may specify
|
32
|
+
an account that may be used for subsequent SSH access and provisioning
|
33
|
+
by setting the `ssh_username` attribute within the provider config
|
34
|
+
section.
|
23
35
|
|
24
36
|
## Supported Guests/Hosts
|
25
37
|
|
26
|
-
|
38
|
+
The project is currently in alpha state and has been tested on the
|
39
|
+
following hosts and guests:
|
27
40
|
|
28
41
|
Hosts:
|
29
42
|
|
30
43
|
* Ubuntu 12.04
|
44
|
+
* Mac OS X
|
31
45
|
|
32
46
|
Guests:
|
33
47
|
|
@@ -36,7 +50,9 @@ Guests:
|
|
36
50
|
|
37
51
|
## Supported Provisioners
|
38
52
|
|
39
|
-
The shell provisioner is supported by default but other provisioners require
|
53
|
+
The shell provisioner is supported by default but other provisioners require
|
54
|
+
bootstrapping on the server. Chef is currently the only supported provisioner.
|
55
|
+
Adding support for puppet and others requires adding the install scripts.
|
40
56
|
|
41
57
|
## Installation
|
42
58
|
|
@@ -44,13 +60,16 @@ Installation is performed in the prescribed manner for Vagrant 1.1 plugins.
|
|
44
60
|
|
45
61
|
vagrant plugin install vagrant-digitalocean
|
46
62
|
|
47
|
-
In addition to installing the plugin the default box associated with the
|
63
|
+
In addition to installing the plugin the default box associated with the
|
64
|
+
provider needs to be installed.
|
48
65
|
|
49
66
|
vagrant box add digital_ocean https://raw.github.com/johnbender/vagrant-digitalocean/master/box/digital_ocean.box
|
50
67
|
|
51
68
|
## Usage
|
52
69
|
|
53
|
-
To use the Digital Ocean provider you will need to visit the
|
70
|
+
To use the Digital Ocean provider you will need to visit the
|
71
|
+
[API access page](https://www.digitalocean.com/api_access) to retrieve
|
72
|
+
the client identifier and API key associated with your account.
|
54
73
|
|
55
74
|
### Config
|
56
75
|
|
@@ -67,7 +86,8 @@ Vagrant.configure("2") do |config|
|
|
67
86
|
vm.region = "New York 1"
|
68
87
|
vm.size = "512MB"
|
69
88
|
vm.ssh_key_name = "My Key"
|
70
|
-
vm.
|
89
|
+
vm.ssh_private_key_path = "~/.ssh/id_rsa"
|
90
|
+
vm.ssh_username = "test"
|
71
91
|
|
72
92
|
# optional config for SSL cert on OSX and others
|
73
93
|
vm.ca_path = "/usr/local/etc/openssl/ca-bundle.crt"
|
data/bin/build.sh
CHANGED
data/bin/test_run.sh
CHANGED
data/box/Vagrantfile
CHANGED
data/lib/vagrant-digitalocean.rb
CHANGED
@@ -8,12 +8,5 @@ module VagrantPlugins
|
|
8
8
|
def self.source_root
|
9
9
|
@source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
|
10
10
|
end
|
11
|
-
|
12
|
-
def self.vagrant_key
|
13
|
-
file = File.open(Vagrant.source_root + "keys/vagrant.pub")
|
14
|
-
key = file.read
|
15
|
-
file.close
|
16
|
-
key
|
17
|
-
end
|
18
11
|
end
|
19
12
|
end
|
@@ -1,15 +1,19 @@
|
|
1
1
|
require "vagrant-digitalocean/actions/destroy"
|
2
2
|
require "vagrant-digitalocean/actions/read_state"
|
3
3
|
require "vagrant-digitalocean/actions/setup_provisioner"
|
4
|
-
require "vagrant-digitalocean/actions/setup_nfs"
|
5
4
|
require "vagrant-digitalocean/actions/setup_sudo"
|
6
|
-
require "vagrant-digitalocean/actions/setup_user"
|
7
5
|
require "vagrant-digitalocean/actions/create"
|
6
|
+
require "vagrant-digitalocean/actions/setup_ssh_key"
|
7
|
+
require "vagrant-digitalocean/actions/sync_folders"
|
8
|
+
require "vagrant-digitalocean/actions/rebuild"
|
9
|
+
require "vagrant-digitalocean/actions/is_active"
|
10
|
+
require "vagrant-digitalocean/actions/message_is_active"
|
11
|
+
require "vagrant-digitalocean/actions/check_ssh_user"
|
12
|
+
require "vagrant-digitalocean/actions/modify_provision_path"
|
8
13
|
|
9
14
|
module VagrantPlugins
|
10
15
|
module DigitalOcean
|
11
16
|
class Action
|
12
|
-
# Include the built-in callable actions, eg SSHExec
|
13
17
|
include Vagrant::Action::Builtin
|
14
18
|
|
15
19
|
def action(name)
|
@@ -19,7 +23,13 @@ module VagrantPlugins
|
|
19
23
|
def destroy
|
20
24
|
return Vagrant::Action::Builder.new.tap do |builder|
|
21
25
|
builder.use ConfigValidate
|
22
|
-
builder.use Actions::
|
26
|
+
builder.use Call, Actions::IsActive do |env, b|
|
27
|
+
if !env[:is_active]
|
28
|
+
b.use Actions::MessageIsActive
|
29
|
+
next
|
30
|
+
end
|
31
|
+
b.use Actions::Destroy
|
32
|
+
end
|
23
33
|
end
|
24
34
|
end
|
25
35
|
|
@@ -33,43 +43,61 @@ module VagrantPlugins
|
|
33
43
|
def ssh
|
34
44
|
return Vagrant::Action::Builder.new.tap do |builder|
|
35
45
|
builder.use ConfigValidate
|
36
|
-
builder.use
|
46
|
+
builder.use Call, Actions::IsActive do |env, b|
|
47
|
+
if !env[:is_active]
|
48
|
+
b.use Actions::MessageIsActive
|
49
|
+
next
|
50
|
+
end
|
51
|
+
b.use Actions::CheckSSHUser
|
52
|
+
b.use SSHExec
|
53
|
+
end
|
37
54
|
end
|
38
55
|
end
|
39
56
|
|
40
57
|
def provision
|
41
58
|
return Vagrant::Action::Builder.new.tap do |builder|
|
42
59
|
builder.use ConfigValidate
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
# set the host and remote ips for NFS
|
57
|
-
builder.use Actions::SetupNFS
|
58
|
-
|
59
|
-
# mount the nfs folders which should be all shared folders
|
60
|
-
builder.use NFS
|
60
|
+
builder.use Call, Actions::IsActive do |env, b|
|
61
|
+
if !env[:is_active]
|
62
|
+
b.use Actions::MessageIsActive
|
63
|
+
next
|
64
|
+
end
|
65
|
+
b.use Actions::CheckSSHUser
|
66
|
+
b.use Actions::ModifyProvisionPath
|
67
|
+
b.use Provision
|
68
|
+
b.use Actions::SetupSudo
|
69
|
+
b.use Actions::SetupProvisioner
|
70
|
+
b.use Actions::SyncFolders
|
71
|
+
end
|
61
72
|
end
|
62
73
|
end
|
63
74
|
|
64
75
|
def up
|
65
|
-
# TODO figure out when to exit if the vm is created
|
66
76
|
return Vagrant::Action::Builder.new.tap do |builder|
|
67
77
|
builder.use ConfigValidate
|
78
|
+
builder.use Call, Actions::IsActive do |env, b|
|
79
|
+
if env[:is_active]
|
80
|
+
b.use Actions::MessageIsActive
|
81
|
+
next
|
82
|
+
end
|
83
|
+
b.use Actions::SetupSSHKey
|
84
|
+
b.use Actions::Create
|
85
|
+
b.use provision
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
68
89
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
builder.use
|
90
|
+
def rebuild
|
91
|
+
return Vagrant::Action::Builder.new.tap do |builder|
|
92
|
+
builder.use ConfigValidate
|
93
|
+
builder.use Call, Actions::IsActive do |env, b|
|
94
|
+
if !env[:is_active]
|
95
|
+
b.use Actions::MessageIsActive
|
96
|
+
next
|
97
|
+
end
|
98
|
+
b.use Actions::Rebuild
|
99
|
+
b.use provision
|
100
|
+
end
|
73
101
|
end
|
74
102
|
end
|
75
103
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module DigitalOcean
|
3
|
+
module Actions
|
4
|
+
class CheckSSHUser
|
5
|
+
include Vagrant::Util::Counter
|
6
|
+
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
@machine = env[:machine]
|
10
|
+
@translator = Helpers::Translator.new("actions.check_ssh_user")
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
# return if the machine is set with the default ssh username
|
15
|
+
return @app.call(env) if @machine.ssh_info()[:username] == "root"
|
16
|
+
|
17
|
+
# check if ssh username account has been provisioned
|
18
|
+
begin
|
19
|
+
tries = @machine.config.ssh.max_tries
|
20
|
+
@machine.config.ssh.max_tries = 0
|
21
|
+
@machine.communicate.execute("echo")
|
22
|
+
rescue Vagrant::Errors::SSHAuthenticationFailed
|
23
|
+
original_username = @machine.ssh_info()[:username]
|
24
|
+
@machine.provider_config.ssh_username = "root"
|
25
|
+
env[:ui].info @translator.t('fallback', {
|
26
|
+
:user => original_username
|
27
|
+
})
|
28
|
+
|
29
|
+
# TODO remove when vagrant chef provisioning defect fixed
|
30
|
+
@machine.config.ssh.username = "root"
|
31
|
+
end
|
32
|
+
|
33
|
+
@machine.config.ssh.max_tries = tries
|
34
|
+
|
35
|
+
@app.call(env)
|
36
|
+
|
37
|
+
# reset ssh username
|
38
|
+
@machine.provider_config.ssh_username = original_username
|
39
|
+
|
40
|
+
# TODO remove when vagrant chef provisioning defect fixed
|
41
|
+
@machine.config.ssh.username = original_username
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -14,28 +14,7 @@ module VagrantPlugins
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def call(env)
|
17
|
-
|
18
|
-
if env[:machine].state.id == :active
|
19
|
-
env[:ui].info @translator.t("skip")
|
20
|
-
return @app.call(env)
|
21
|
-
end
|
22
|
-
|
23
|
-
# TODO check the content of the key to see if it has changed
|
24
|
-
ssh_key_name = env[:machine].provider_config.ssh_key_name
|
25
|
-
begin
|
26
|
-
ssh_key_id = @client
|
27
|
-
.request("/ssh_keys/")
|
28
|
-
.find_id(:ssh_keys, :name => ssh_key_name)
|
29
|
-
rescue Errors::ResultMatchError
|
30
|
-
env[:ui].info @translator.t("create_key")
|
31
|
-
|
32
|
-
result = @client.request("/ssh_keys/new", {
|
33
|
-
:name => ssh_key_name,
|
34
|
-
:ssh_pub_key => pub_ssh_key(env)
|
35
|
-
})
|
36
|
-
|
37
|
-
ssh_key_id = result["ssh_key"]["id"]
|
38
|
-
end
|
17
|
+
ssh_key_id = env[:ssh_key_id]
|
39
18
|
|
40
19
|
size_id = @client
|
41
20
|
.request("/sizes")
|
@@ -60,21 +39,11 @@ module VagrantPlugins
|
|
60
39
|
:ssh_key_ids => ssh_key_id
|
61
40
|
})
|
62
41
|
|
63
|
-
# assign the machine id for reference in other commands
|
64
|
-
env[:machine].id = result["droplet"]["id"].to_s
|
65
|
-
|
66
42
|
env[:ui].info @translator.t("wait_active")
|
43
|
+
@client.wait_for_event(result["droplet"]["event_id"])
|
67
44
|
|
68
|
-
|
69
|
-
|
70
|
-
next if env[:interrupted]
|
71
|
-
|
72
|
-
# Wait for the server to be ready
|
73
|
-
raise "not ready" if env[:machine].state.id != :active
|
74
|
-
end
|
75
|
-
|
76
|
-
# signal that the machine has just been created, used in ReadState
|
77
|
-
env[:machine_just_created] = true
|
45
|
+
# assign the machine id for reference in other commands
|
46
|
+
env[:machine].id = result["droplet"]["id"].to_s
|
78
47
|
|
79
48
|
@app.call(env)
|
80
49
|
end
|
@@ -96,19 +65,6 @@ module VagrantPlugins
|
|
96
65
|
destroy_env[:force_confirm_destroy] = true
|
97
66
|
env[:action_runner].run(Action.new.destroy, destroy_env)
|
98
67
|
end
|
99
|
-
|
100
|
-
private
|
101
|
-
|
102
|
-
def pub_ssh_key(env)
|
103
|
-
path = env[:machine].provider_config.pub_ssh_key_path
|
104
|
-
file = File.open(File.expand_path(path))
|
105
|
-
key = file.read
|
106
|
-
file.close
|
107
|
-
key
|
108
|
-
rescue
|
109
|
-
env[:ui].info @translator.t("key_not_found")
|
110
|
-
DigitalOcean.vagrant_key
|
111
|
-
end
|
112
68
|
end
|
113
69
|
end
|
114
70
|
end
|
@@ -14,28 +14,13 @@ module VagrantPlugins
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def call(env)
|
17
|
-
#
|
18
|
-
|
19
|
-
|
20
|
-
result = @client.request("/droplets/#{env[:machine].id}/destroy")
|
17
|
+
# submit destroy droplet request
|
18
|
+
env[:ui].info @translator.t("destroying")
|
19
|
+
result = @client.request("/droplets/#{env[:machine].id}/destroy")
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
# If we're interrupted don't worry about waiting
|
26
|
-
next if env[:interrupted]
|
27
|
-
|
28
|
-
# Wait for the server to be ready
|
29
|
-
raise "not off" if env[:machine].state.id != :off
|
30
|
-
end
|
31
|
-
else
|
32
|
-
env[:ui].info @translator.t("not_active_or_new")
|
33
|
-
end
|
34
|
-
|
35
|
-
# make sure to remove the export when the machine is destroyed
|
36
|
-
# private in some hosts and requires a send
|
37
|
-
env[:ui].info @translator.t("clean_nfs")
|
38
|
-
env[:host].send(:nfs_cleanup, env[:machine].id.to_s)
|
21
|
+
# wait for request to complete
|
22
|
+
env[:ui].info @translator.t("wait_off")
|
23
|
+
@client.wait_for_event(result["event_id"])
|
39
24
|
|
40
25
|
@app.call(env)
|
41
26
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module DigitalOcean
|
3
|
+
module Actions
|
4
|
+
class IsActive
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
env[:is_active] = env[:machine].state.id == :active
|
11
|
+
@app.call(env)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module DigitalOcean
|
3
|
+
module Actions
|
4
|
+
class MessageIsActive
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
@translator = Helpers::Translator.new("actions.message_is_active")
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
msg = env[:is_active] ? "active" : "not_active"
|
12
|
+
env[:ui].info @translator.t(msg)
|
13
|
+
@app.call(env)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module DigitalOcean
|
3
|
+
module Actions
|
4
|
+
class ModifyProvisionPath
|
5
|
+
include Vagrant::Util::Counter
|
6
|
+
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
@machine = env[:machine]
|
10
|
+
@translator =
|
11
|
+
Helpers::Translator.new("actions.modify_provision_path")
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
username = @machine.ssh_info()[:username]
|
16
|
+
env[:ui].info @translator.t("modify", { :user => username })
|
17
|
+
|
18
|
+
# modify provisioning paths to enable different users to
|
19
|
+
# provision the same machine
|
20
|
+
#
|
21
|
+
# TODO submit patch to vagrant to set appropriate permissions
|
22
|
+
# based on ssh username
|
23
|
+
@machine.communicate.execute("mkdir -p /home/#{username}/tmp")
|
24
|
+
env[:global_config].vm.provisioners.each do |prov|
|
25
|
+
if prov.name == :shell
|
26
|
+
prov.config.upload_path =
|
27
|
+
prov.config.upload_path.prepend("/home/#{username}")
|
28
|
+
else
|
29
|
+
counter = get_and_update_counter(:provisioning_path)
|
30
|
+
path = "/home/#{username}/tmp/vagrant-chef-#{counter}"
|
31
|
+
prov.config.provisioning_path = path
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
@app.call(env)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "vagrant-digitalocean/helpers/client"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module DigitalOcean
|
5
|
+
module Actions
|
6
|
+
class Rebuild
|
7
|
+
include Helpers::Client
|
8
|
+
|
9
|
+
def initialize(app, env)
|
10
|
+
@app, @env = app, env
|
11
|
+
@client = client
|
12
|
+
@translator = Helpers::Translator.new("actions.rebuild")
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
# look up image id
|
17
|
+
image_id = @client
|
18
|
+
.request("/images", { :filter => "global" })
|
19
|
+
.find_id(:images, :name => env[:machine].provider_config.image)
|
20
|
+
|
21
|
+
# submit rebuild request
|
22
|
+
env[:ui].info @translator.t("rebuild")
|
23
|
+
result = @client.request("/droplets/#{env[:machine].id}/rebuild", {
|
24
|
+
:image_id => image_id
|
25
|
+
})
|
26
|
+
|
27
|
+
# wait for request to complete
|
28
|
+
env[:ui].info @translator.t("wait")
|
29
|
+
@client.wait_for_event(result["event_id"])
|
30
|
+
|
31
|
+
@app.call(env)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "vagrant-digitalocean/helpers/client"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module DigitalOcean
|
5
|
+
module Actions
|
6
|
+
class SetupSSHKey
|
7
|
+
include Helpers::Client
|
8
|
+
|
9
|
+
def initialize(app, env)
|
10
|
+
@app, @env = app, env
|
11
|
+
@client = client
|
12
|
+
@translator = Helpers::Translator.new("actions.setup_ssh_key")
|
13
|
+
end
|
14
|
+
|
15
|
+
# TODO check the content of the key to see if it has changed
|
16
|
+
def call(env)
|
17
|
+
ssh_key_name = env[:machine].provider_config.ssh_key_name
|
18
|
+
|
19
|
+
begin
|
20
|
+
# assigns existing ssh key id to env for use by other commands
|
21
|
+
env[:ssh_key_id] = @client
|
22
|
+
.request("/ssh_keys/")
|
23
|
+
.find_id(:ssh_keys, :name => ssh_key_name)
|
24
|
+
|
25
|
+
env[:ui].info @translator.t("existing_key", { :name => ssh_key_name })
|
26
|
+
rescue Errors::ResultMatchError
|
27
|
+
env[:ssh_key_id] = create_ssh_key(ssh_key_name, env)
|
28
|
+
end
|
29
|
+
|
30
|
+
@app.call(env)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def create_ssh_key(name, env)
|
36
|
+
# assumes public key exists on the same path as private key with .pub ext
|
37
|
+
path = env[:machine].provider_config.ssh_private_key_path
|
38
|
+
path = env[:machine].config.ssh.private_key_path if !path
|
39
|
+
path = File.expand_path("#{path}.pub", env[:machine].env.root_path)
|
40
|
+
|
41
|
+
env[:ui].info @translator.t("new_key", { :name => name, :path => path })
|
42
|
+
begin
|
43
|
+
file = File.open(path)
|
44
|
+
key = file.read
|
45
|
+
file.close
|
46
|
+
rescue
|
47
|
+
raise Errors::PublicKeyError,
|
48
|
+
:path => path
|
49
|
+
end
|
50
|
+
|
51
|
+
result = @client.request("/ssh_keys/new", {
|
52
|
+
:name => name,
|
53
|
+
:ssh_pub_key => key
|
54
|
+
})
|
55
|
+
result["ssh_key"]["id"]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "vagrant/util/subprocess"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module DigitalOcean
|
5
|
+
module Actions
|
6
|
+
# This middleware uses `rsync` to sync the folders over to the
|
7
|
+
# Digital Ocean instance. The implementation was lifted from the
|
8
|
+
# vagrant-aws provider plugin.
|
9
|
+
class SyncFolders
|
10
|
+
def initialize(app, env)
|
11
|
+
@app, @env = app, env
|
12
|
+
@translator = Helpers::Translator.new("actions.sync_folders")
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
@app.call(env)
|
17
|
+
|
18
|
+
ssh_info = env[:machine].ssh_info
|
19
|
+
|
20
|
+
env[:machine].config.vm.synced_folders.each do |id, data|
|
21
|
+
hostpath = File.expand_path(data[:hostpath], env[:root_path])
|
22
|
+
guestpath = data[:guestpath]
|
23
|
+
|
24
|
+
# Make sure there is a trailing slash on the host path to
|
25
|
+
# avoid creating an additional directory with rsync
|
26
|
+
hostpath = "#{hostpath}/" if hostpath !~ /\/$/
|
27
|
+
|
28
|
+
env[:ui].info @translator.t("rsync_folder",
|
29
|
+
:hostpath => hostpath,
|
30
|
+
:guestpath => guestpath)
|
31
|
+
|
32
|
+
# Create the guest path
|
33
|
+
env[:machine].communicate.sudo("mkdir -p #{guestpath}")
|
34
|
+
env[:machine].communicate.sudo(
|
35
|
+
"chown -R #{ssh_info[:username]} #{guestpath}")
|
36
|
+
|
37
|
+
# Rsync over to the guest path using the SSH info
|
38
|
+
command = [
|
39
|
+
"rsync", "--verbose", "--archive", "-z",
|
40
|
+
"-e", "ssh -p #{ssh_info[:port]} -o StrictHostKeyChecking=no -i '#{ssh_info[:private_key_path]}'",
|
41
|
+
hostpath,
|
42
|
+
"#{ssh_info[:username]}@#{ssh_info[:host]}:#{guestpath}"]
|
43
|
+
|
44
|
+
r = Vagrant::Util::Subprocess.execute(*command)
|
45
|
+
if r.exit_code != 0
|
46
|
+
raise Errors::RsyncError,
|
47
|
+
:guestpath => guestpath,
|
48
|
+
:hostpath => hostpath,
|
49
|
+
:stderr => r.stderr
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module DigitalOcean
|
5
|
+
module Commands
|
6
|
+
class Rebuild < Vagrant.plugin("2", :command)
|
7
|
+
def execute
|
8
|
+
opts = OptionParser.new do |o|
|
9
|
+
o.banner = "Usage: vagrant rebuild [vm-name]"
|
10
|
+
end
|
11
|
+
|
12
|
+
argv = parse_options(opts)
|
13
|
+
return if !argv
|
14
|
+
|
15
|
+
with_target_vms(argv) do |machine|
|
16
|
+
machine.action(:rebuild)
|
17
|
+
end
|
18
|
+
|
19
|
+
0
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -2,34 +2,49 @@ module VagrantPlugins
|
|
2
2
|
module DigitalOcean
|
3
3
|
class Config < Vagrant.plugin("2", :config)
|
4
4
|
attr_accessor :client_id, :api_key, :image, :region, :size, :ca_path,
|
5
|
-
:ssh_key_name, :
|
5
|
+
:ssh_key_name, :ssh_private_key_path, :ssh_username
|
6
6
|
|
7
7
|
def initialize
|
8
|
-
@client_id
|
9
|
-
@api_key
|
10
|
-
@image
|
11
|
-
@region
|
12
|
-
@size
|
13
|
-
@ca_path
|
14
|
-
@ssh_key_name
|
15
|
-
@
|
8
|
+
@client_id = UNSET_VALUE
|
9
|
+
@api_key = UNSET_VALUE
|
10
|
+
@image = UNSET_VALUE
|
11
|
+
@region = UNSET_VALUE
|
12
|
+
@size = UNSET_VALUE
|
13
|
+
@ca_path = UNSET_VALUE
|
14
|
+
@ssh_key_name = UNSET_VALUE
|
15
|
+
@ssh_private_key_path = UNSET_VALUE
|
16
|
+
@ssh_username = UNSET_VALUE
|
17
|
+
|
18
|
+
@translator = Helpers::Translator.new("config")
|
16
19
|
end
|
17
20
|
|
18
21
|
def finalize!
|
19
|
-
@client_id
|
20
|
-
@api_key
|
21
|
-
@image
|
22
|
-
@region
|
23
|
-
@size
|
24
|
-
@ca_path
|
25
|
-
@ssh_key_name
|
26
|
-
@
|
22
|
+
@client_id = ENV["DO_CLIENT_ID"] if @client_id == UNSET_VALUE
|
23
|
+
@api_key = ENV["DO_API_KEY"] if @api_key == UNSET_VALUE
|
24
|
+
@image = "Ubuntu 12.04 x32 Server" if @image == UNSET_VALUE
|
25
|
+
@region = "New York 1" if @region == UNSET_VALUE
|
26
|
+
@size = "512MB" if @size == UNSET_VALUE
|
27
|
+
@ca_path = nil if @ca_path == UNSET_VALUE
|
28
|
+
@ssh_key_name = "Vagrant" if @ssh_key_name == UNSET_VALUE
|
29
|
+
@ssh_private_key_path = nil if @ssh_private_key_path == UNSET_VALUE
|
30
|
+
@ssh_username = "root" if @ssh_username == UNSET_VALUE
|
27
31
|
end
|
28
32
|
|
29
33
|
def validate(machine)
|
30
34
|
errors = []
|
31
|
-
errors <<
|
32
|
-
errors <<
|
35
|
+
errors << @translator.t(:client_id_required) if !@client_id
|
36
|
+
errors << @translator.t(:api_key_required) if !@api_key
|
37
|
+
|
38
|
+
key = @ssh_private_key_path
|
39
|
+
key = machine.config.ssh.private_key_path if !@ssh_private_key_path
|
40
|
+
|
41
|
+
if !key
|
42
|
+
errors << @translator.t(:private_key_required) if !key
|
43
|
+
elsif !File.file?(File.expand_path(key, machine.env.root_path))
|
44
|
+
errors << @translator.t(:private_key_missing, { :key => key })
|
45
|
+
elsif !File.file?(File.expand_path("#{key}.pub", machine.env.root_path))
|
46
|
+
errors << @translator.t(:public_key_missing, { :key => key })
|
47
|
+
end
|
33
48
|
|
34
49
|
{ "Digital Ocean Provider" => errors }
|
35
50
|
end
|
@@ -26,6 +26,14 @@ module VagrantPlugins
|
|
26
26
|
class LocalIPError < DigitalOceanError
|
27
27
|
error_key(:local_ip)
|
28
28
|
end
|
29
|
+
|
30
|
+
class PublicKeyError < DigitalOceanError
|
31
|
+
error_key(:public_key)
|
32
|
+
end
|
33
|
+
|
34
|
+
class RsyncError < DigitalOceanError
|
35
|
+
error_key(:rsync)
|
36
|
+
end
|
29
37
|
end
|
30
38
|
end
|
31
39
|
end
|
@@ -7,17 +7,20 @@ module VagrantPlugins
|
|
7
7
|
module Helpers
|
8
8
|
module Client
|
9
9
|
def client
|
10
|
-
@client ||= ApiClient.new(@env
|
10
|
+
@client ||= ApiClient.new(@env)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
14
|
class ApiClient
|
15
|
-
|
16
|
-
|
15
|
+
include Vagrant::Util::Retryable
|
16
|
+
|
17
|
+
def initialize(env)
|
18
|
+
@env = env
|
19
|
+
@config = env[:machine].provider_config
|
17
20
|
@client = Faraday.new({
|
18
21
|
:url => "https://api.digitalocean.com/",
|
19
22
|
:ssl => {
|
20
|
-
:ca_file => config.ca_path
|
23
|
+
:ca_file => @config.ca_path
|
21
24
|
}
|
22
25
|
})
|
23
26
|
end
|
@@ -64,6 +67,20 @@ module VagrantPlugins
|
|
64
67
|
|
65
68
|
Result.new(body)
|
66
69
|
end
|
70
|
+
|
71
|
+
def wait_for_event(id)
|
72
|
+
retryable(:tries => 30, :sleep => 10) do
|
73
|
+
# stop waiting if interrupted
|
74
|
+
next if @env[:interrupted]
|
75
|
+
|
76
|
+
|
77
|
+
# check event status
|
78
|
+
result = self.request("/events/#{id}")
|
79
|
+
|
80
|
+
yield result if block_given?
|
81
|
+
raise "not ready" if result["event"]["action_status"] != "done"
|
82
|
+
end
|
83
|
+
end
|
67
84
|
end
|
68
85
|
end
|
69
86
|
end
|
@@ -57,19 +57,14 @@ module VagrantPlugins
|
|
57
57
|
|
58
58
|
return nil if state["status"] == :not_created
|
59
59
|
|
60
|
-
|
61
|
-
|
62
|
-
elsif @machine.provider_config.pub_ssh_key_path
|
63
|
-
private_key_path = @machine.provider_config.pub_ssh_key_path.chomp(".pub")
|
64
|
-
else
|
65
|
-
private_key_path = Vagrant.source_root + "keys/vagrant"
|
66
|
-
end
|
60
|
+
# TODO remove when defect in vagrant chef provisioner is fixed
|
61
|
+
@machine.config.ssh.username = @machine.provider_config.ssh_username
|
67
62
|
|
68
63
|
return {
|
69
64
|
:host => state["ip_address"],
|
70
65
|
:port => "22",
|
71
|
-
:username =>
|
72
|
-
:private_key_path =>
|
66
|
+
:username => @machine.provider_config.ssh_username,
|
67
|
+
:private_key_path => @machine.provider_config.ssh_private_key_path
|
73
68
|
}
|
74
69
|
end
|
75
70
|
|
data/locales/en.yml
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
en:
|
2
2
|
vagrant_digital_ocean:
|
3
|
+
config:
|
4
|
+
client_id_required: "Client ID required"
|
5
|
+
api_key_required: "API key required"
|
6
|
+
private_key_required: "SSH private key path required"
|
7
|
+
private_key_missing: "SSH private key is missing: %{key}"
|
8
|
+
public_key_missing: "SSH public key is missing: %{key}.pub"
|
3
9
|
errors:
|
10
|
+
public_key: "Failed to read public key: %{path}"
|
4
11
|
api_status: |-
|
5
12
|
There was an issue with the request made to the Digital Ocean
|
6
13
|
API at:
|
@@ -12,6 +19,15 @@ en:
|
|
12
19
|
|
13
20
|
Status: %{status}
|
14
21
|
Response: %{response}
|
22
|
+
|
23
|
+
rsync: |-
|
24
|
+
There was an error when attemping to rsync a share folder.
|
25
|
+
Please inspect the error message below for more info.
|
26
|
+
|
27
|
+
Host path: %{hostpath}
|
28
|
+
Guest path: %{guestpath}
|
29
|
+
Error: %{stderr}
|
30
|
+
|
15
31
|
:json: |-
|
16
32
|
There was an issue with the JSON response from the Digital Ocean
|
17
33
|
API at:
|
@@ -48,26 +64,28 @@ en:
|
|
48
64
|
|
49
65
|
actions:
|
50
66
|
create:
|
51
|
-
skip: "Droplet is active, skipping creation"
|
52
|
-
create_key: "Adding key client account"
|
53
67
|
create_droplet: "Creating the droplet"
|
54
68
|
wait_active: "Waiting for the droplet to become active (>= 1 min)"
|
55
|
-
|
69
|
+
rebuild:
|
70
|
+
rebuild: "Rebuilding the droplet"
|
71
|
+
wait: "Waiting for the droplet to rebuild (>= 1 min)"
|
56
72
|
destroy:
|
57
73
|
destroying: "Destroying droplet"
|
58
|
-
not_active_or_new: "Droplet not in the `active` or `new` state"
|
59
|
-
clean_nfs: "Cleaning up NFS exports, may require sudo password"
|
60
74
|
wait_off: "Waiting for the droplet to be destroyed"
|
61
75
|
setup_sudo:
|
62
76
|
exec: "Making alterations to the sudoers file where necessary"
|
63
|
-
setup_nfs:
|
64
|
-
machine_ip: "Droplet IP: %{ip}"
|
65
|
-
host_ip: "Host IP: %{ip}"
|
66
|
-
install: "Installing NFS on the droplet"
|
67
|
-
force_shared_folders: "Forcing shared folders to use NFS where necessary"
|
68
77
|
setup_provisioner:
|
69
78
|
install: "Installing provisioner: %{provisioner} (>= 2 min)"
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
79
|
+
sync_folders:
|
80
|
+
rsync_folder: "Rsyncing folder: %{hostpath} => %{guestpath}"
|
81
|
+
setup_ssh_key:
|
82
|
+
existing_key: "Using existing SSH key: %{name}"
|
83
|
+
insecure_key: "Using default insecure vagrant SSH key"
|
84
|
+
new_key: "Creating new SSH key: %{name} (%{path})"
|
85
|
+
message_is_active:
|
86
|
+
active: "Droplet is already active"
|
87
|
+
not_active: "Droplet is not active"
|
88
|
+
check_ssh_user:
|
89
|
+
fallback: "Failed to authenticate with '%{user}', falling back to 'root'"
|
90
|
+
modify_provision_path:
|
91
|
+
modify: "Modifying provisioning path to '/home/%{user}/tmp'"
|
data/test/Vagrantfile.centos
CHANGED
data/test/Vagrantfile.ubuntu
CHANGED
@@ -8,10 +8,11 @@ Vagrant.configure("2") do |config|
|
|
8
8
|
vm.region = "New York 1"
|
9
9
|
vm.size = "512MB"
|
10
10
|
vm.ssh_key_name = "Test Key"
|
11
|
-
vm.
|
11
|
+
vm.ssh_private_key_path = "test_id_rsa"
|
12
|
+
vm.ssh_username = "tester"
|
12
13
|
end
|
13
14
|
|
14
|
-
config.vm.provision :shell, :path => "
|
15
|
+
config.vm.provision :shell, :path => "scripts/setup_user.sh"
|
15
16
|
|
16
17
|
config.vm.provision :chef_solo do |chef|
|
17
18
|
chef.cookbooks_path = "cookbooks"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
if ! grep tester /etc/passwd; then
|
4
|
+
useradd -m -s /bin/bash tester
|
5
|
+
fi
|
6
|
+
|
7
|
+
if ! grep tester /etc/sudoers; then
|
8
|
+
echo "tester ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers
|
9
|
+
fi
|
10
|
+
|
11
|
+
mkdir -p /home/tester/.ssh
|
12
|
+
chown tester:tester /home/tester/.ssh
|
13
|
+
|
14
|
+
pub_key="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCbFlHJ++BcXGU9b2K+jF990r16uqkKnWiK2CFS0PFvM9IJs3CoGiIlyc9UD9O4LEyeu5Rw0RdiAp9MvyUPcDUeibw3WlMCFJ53mbioAapMy5tPXmxxJH5KcN2uJKESsH/1hJv0tWfVpHQywVLcf/7HWPjDl3qEFqzwGEN+5V3XqyG+hoA4rLTLDL40G68bL/oC7ere3sz3B16U4NGdgtJZapot5gTFErFZZztql76h25Ch7isE1XAaYg6NY4z1oU8Q9Ud0sY74tDI8TF165LStb3prf1TinwaMbOyuQ1wrNU4aMzekiwazeo6LtHMnfPjweIGP01PwjZ8WkYcRF6tt digital_ocean provider test key"
|
15
|
+
|
16
|
+
if ! [ -e /home/tester/.ssh/authorized_keys ]; then
|
17
|
+
echo "${pub_key}" > /home/tester/.ssh/authorized_keys
|
18
|
+
fi
|
@@ -5,14 +5,13 @@ require 'vagrant-digitalocean/version'
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |gem|
|
7
7
|
gem.name = "vagrant-digitalocean"
|
8
|
-
gem.version = VagrantPlugins::
|
8
|
+
gem.version = VagrantPlugins::DigitalOcean::VERSION
|
9
9
|
gem.authors = ["John Bender"]
|
10
10
|
gem.email = ["john.m.bender@gmail.com"]
|
11
11
|
gem.description = %q{Enables Vagrant to manage Digital Ocean droplets}
|
12
12
|
gem.summary = gem.description
|
13
13
|
|
14
14
|
gem.files = `git ls-files`.split($/)
|
15
|
-
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
16
15
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
17
16
|
gem.require_paths = ["lib"]
|
18
17
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-digitalocean
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-04-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: faraday
|
@@ -62,9 +62,7 @@ dependencies:
|
|
62
62
|
description: Enables Vagrant to manage Digital Ocean droplets
|
63
63
|
email:
|
64
64
|
- john.m.bender@gmail.com
|
65
|
-
executables:
|
66
|
-
- build.sh
|
67
|
-
- test_run.sh
|
65
|
+
executables: []
|
68
66
|
extensions: []
|
69
67
|
extra_rdoc_files: []
|
70
68
|
files:
|
@@ -81,13 +79,20 @@ files:
|
|
81
79
|
- box/metadata.json
|
82
80
|
- lib/vagrant-digitalocean.rb
|
83
81
|
- lib/vagrant-digitalocean/action.rb
|
82
|
+
- lib/vagrant-digitalocean/actions/check_ssh_user.rb
|
84
83
|
- lib/vagrant-digitalocean/actions/create.rb
|
85
84
|
- lib/vagrant-digitalocean/actions/destroy.rb
|
85
|
+
- lib/vagrant-digitalocean/actions/is_active.rb
|
86
|
+
- lib/vagrant-digitalocean/actions/message_is_active.rb
|
87
|
+
- lib/vagrant-digitalocean/actions/modify_provision_path.rb
|
86
88
|
- lib/vagrant-digitalocean/actions/read_state.rb
|
87
|
-
- lib/vagrant-digitalocean/actions/
|
89
|
+
- lib/vagrant-digitalocean/actions/rebuild.rb
|
88
90
|
- lib/vagrant-digitalocean/actions/setup_provisioner.rb
|
91
|
+
- lib/vagrant-digitalocean/actions/setup_ssh_key.rb
|
89
92
|
- lib/vagrant-digitalocean/actions/setup_sudo.rb
|
90
93
|
- lib/vagrant-digitalocean/actions/setup_user.rb
|
94
|
+
- lib/vagrant-digitalocean/actions/sync_folders.rb
|
95
|
+
- lib/vagrant-digitalocean/commands/rebuild.rb
|
91
96
|
- lib/vagrant-digitalocean/config.rb
|
92
97
|
- lib/vagrant-digitalocean/errors.rb
|
93
98
|
- lib/vagrant-digitalocean/helpers/client.rb
|
@@ -107,6 +112,7 @@ files:
|
|
107
112
|
- test/Vagrantfile.ubuntu
|
108
113
|
- test/cookbooks/test/recipes/default.rb
|
109
114
|
- test/provision.sh
|
115
|
+
- test/scripts/setup_user.sh
|
110
116
|
- test/test_id_rsa
|
111
117
|
- test/test_id_rsa.pub
|
112
118
|
- vagrant-digitalocean.gemspec
|
@@ -139,5 +145,6 @@ test_files:
|
|
139
145
|
- test/Vagrantfile.ubuntu
|
140
146
|
- test/cookbooks/test/recipes/default.rb
|
141
147
|
- test/provision.sh
|
148
|
+
- test/scripts/setup_user.sh
|
142
149
|
- test/test_id_rsa
|
143
150
|
- test/test_id_rsa.pub
|
@@ -1,61 +0,0 @@
|
|
1
|
-
require "socket"
|
2
|
-
|
3
|
-
module VagrantPlugins
|
4
|
-
module DigitalOcean
|
5
|
-
module Actions
|
6
|
-
class SetupNFS
|
7
|
-
include Helpers::File
|
8
|
-
|
9
|
-
def initialize(app, env)
|
10
|
-
@app, @env = app, env
|
11
|
-
@translator = Helpers::Translator.new("actions.setup_nfs")
|
12
|
-
end
|
13
|
-
|
14
|
-
def call(env)
|
15
|
-
# set the nfs machine ip
|
16
|
-
env[:nfs_machine_ip] = env[:machine].provider.ssh_info[:host]
|
17
|
-
env[:ui].info @translator.t("machine_ip", :ip => env[:nfs_machine_ip])
|
18
|
-
|
19
|
-
# get the host ip from the local adapters
|
20
|
-
raise Errors::LocalIPError if !(host_ip = determine_host_ip)
|
21
|
-
|
22
|
-
env[:nfs_host_ip] = host_ip
|
23
|
-
|
24
|
-
env[:ui].info @translator.t("host_ip", :ip => env[:nfs_host_ip])
|
25
|
-
|
26
|
-
# make sure the nfs server is setup
|
27
|
-
env[:ui].info @translator.t("install")
|
28
|
-
env[:machine].communicate.execute(nfs_install(env[:machine].guest))
|
29
|
-
|
30
|
-
vm = env[:machine].config.vm
|
31
|
-
|
32
|
-
# force all shard folders to use nfs
|
33
|
-
env[:ui].warn @translator.t("force_shared_folders")
|
34
|
-
folders = vm.synced_folders.keys.each do |key|
|
35
|
-
vm.synced_folders[key][:nfs] = true
|
36
|
-
end
|
37
|
-
|
38
|
-
@app.call(env)
|
39
|
-
end
|
40
|
-
|
41
|
-
# TODO not thread safe :(
|
42
|
-
# TODO google ip seems like a bad idea
|
43
|
-
def determine_host_ip
|
44
|
-
# turn off reverse DNS resolution temporarily
|
45
|
-
orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true
|
46
|
-
|
47
|
-
UDPSocket.open do |s|
|
48
|
-
s.connect '64.233.187.99', 1
|
49
|
-
s.addr.last
|
50
|
-
end
|
51
|
-
ensure
|
52
|
-
Socket.do_not_reverse_lookup = orig
|
53
|
-
end
|
54
|
-
|
55
|
-
def nfs_install(guest)
|
56
|
-
read_script("nfs", guest)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|