vagrant-digitalocean 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|