vagrant-digitalocean 0.0.4 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. data/.gitignore +1 -1
  2. data/Gemfile +1 -4
  3. data/LICENSE.txt +2 -1
  4. data/README.md +114 -96
  5. data/Rakefile +8 -10
  6. data/box/digital_ocean.box +0 -0
  7. data/lib/vagrant-digitalocean.rb +12 -4
  8. data/lib/vagrant-digitalocean/actions.rb +159 -0
  9. data/lib/vagrant-digitalocean/actions/check_state.rb +19 -0
  10. data/lib/vagrant-digitalocean/actions/create.rb +36 -21
  11. data/lib/vagrant-digitalocean/actions/destroy.rb +10 -8
  12. data/lib/vagrant-digitalocean/actions/modify_provision_path.rb +15 -17
  13. data/lib/vagrant-digitalocean/actions/power_off.rb +33 -0
  14. data/lib/vagrant-digitalocean/actions/power_on.rb +34 -0
  15. data/lib/vagrant-digitalocean/actions/rebuild.rb +9 -9
  16. data/lib/vagrant-digitalocean/actions/reload.rb +31 -0
  17. data/lib/vagrant-digitalocean/actions/setup_key.rb +56 -0
  18. data/lib/vagrant-digitalocean/actions/setup_provisioner.rb +26 -15
  19. data/lib/vagrant-digitalocean/actions/setup_sudo.rb +19 -12
  20. data/lib/vagrant-digitalocean/actions/setup_user.rb +25 -27
  21. data/lib/vagrant-digitalocean/actions/sync_folders.rb +18 -17
  22. data/lib/vagrant-digitalocean/commands/rebuild.rb +2 -3
  23. data/lib/vagrant-digitalocean/config.rb +30 -33
  24. data/lib/vagrant-digitalocean/errors.rb +0 -2
  25. data/lib/vagrant-digitalocean/helpers/client.rb +13 -15
  26. data/lib/vagrant-digitalocean/plugin.rb +5 -14
  27. data/lib/vagrant-digitalocean/provider.rb +48 -34
  28. data/lib/vagrant-digitalocean/version.rb +1 -1
  29. data/locales/en.yml +32 -40
  30. data/test/Vagrantfile +37 -0
  31. data/test/cookbooks/test/recipes/default.rb +1 -1
  32. data/test/scripts/provision.sh +3 -0
  33. data/test/test.sh +14 -0
  34. metadata +15 -27
  35. data/bin/build.sh +0 -39
  36. data/bin/test_run.sh +0 -15
  37. data/box/Vagrantfile +0 -20
  38. data/box/cookbooks/foo/recipes/default.rb +0 -1
  39. data/lib/vagrant-digitalocean/action.rb +0 -105
  40. data/lib/vagrant-digitalocean/actions/check_ssh_user.rb +0 -46
  41. data/lib/vagrant-digitalocean/actions/is_active.rb +0 -16
  42. data/lib/vagrant-digitalocean/actions/message_is_active.rb +0 -18
  43. data/lib/vagrant-digitalocean/actions/read_state.rb +0 -33
  44. data/lib/vagrant-digitalocean/actions/setup_ssh_key.rb +0 -60
  45. data/lib/vagrant-digitalocean/helpers/file.rb +0 -41
  46. data/lib/vagrant-digitalocean/helpers/translator.rb +0 -20
  47. data/scripts/chef/debian.sh +0 -5
  48. data/scripts/chef/redhat.sh +0 -5
  49. data/scripts/nfs/debian.sh +0 -4
  50. data/scripts/nfs/redhat.sh +0 -11
  51. data/scripts/sudo/redhat.sh +0 -2
  52. data/test/Vagrantfile.centos +0 -19
  53. data/test/Vagrantfile.ubuntu +0 -21
  54. data/test/provision.sh +0 -3
  55. data/test/scripts/setup_user.sh +0 -18
@@ -1,25 +1,32 @@
1
- require "vagrant-digitalocean/helpers/file"
2
-
3
1
  module VagrantPlugins
4
2
  module DigitalOcean
5
3
  module Actions
6
4
  class SetupSudo
7
- include Helpers::File
8
-
9
5
  def initialize(app, env)
10
- @app, @env = app, env
11
- @translator = Helpers::Translator.new("actions.setup_sudo")
6
+ @app = app
7
+ @machine = env[:machine]
8
+ @logger = Log4r::Logger.new('vagrant::digitalocean::setup_sudo')
12
9
  end
13
10
 
14
11
  def call(env)
15
- env[:ui].info @translator.t("exec")
16
- env[:machine].communicate.execute(fix_sudo(env[:machine].guest))
12
+ # override ssh username to root temporarily
13
+ user = @machine.config.ssh.username
14
+ @machine.config.ssh.username = 'root'
17
15
 
18
- @app.call(env)
19
- end
16
+ case @machine.guest.to_s
17
+ when /RedHat/
18
+ env[:ui].info I18n.t('vagrant_digital_ocean.info.modifying_sudo')
20
19
 
21
- def fix_sudo(guest)
22
- read_script("sudo", guest, false)
20
+ # disable tty requirement for sudo
21
+ @machine.communicate.execute(<<-'BASH')
22
+ sed -i'.bk' -e 's/\(Defaults\s\+requiretty\)/# \1/' /etc/sudoers
23
+ BASH
24
+ end
25
+
26
+ # reset ssh username
27
+ @machine.config.ssh.username = user
28
+
29
+ @app.call(env)
23
30
  end
24
31
  end
25
32
  end
@@ -3,56 +3,54 @@ module VagrantPlugins
3
3
  module Actions
4
4
  class SetupUser
5
5
  def initialize(app, env)
6
- @app, @env = app, env
7
- @translator = Helpers::Translator.new("actions.setup_user")
6
+ @app = app
7
+ @machine = env[:machine]
8
+ @logger = Log4r::Logger.new('vagrant::digitalocean::setup_user')
8
9
  end
9
10
 
10
11
  def call(env)
11
- # create the user, set the password to username, add to sudoers
12
- # NOTE assumes group with username is created with useradd
13
- env[:ui].info @translator.t("create", :user => user)
14
- env[:machine].communicate.execute(<<-BASH)
12
+ # check if a username has been specified
13
+ return @app.call(env) if !@machine.config.ssh.username
14
+
15
+ # override ssh username to root temporarily
16
+ user = @machine.config.ssh.username
17
+ @machine.config.ssh.username = 'root'
18
+
19
+ env[:ui].info I18n.t('vagrant_digital_ocean.info.creating_user', {
20
+ :user => user
21
+ })
22
+
23
+ # create user account
24
+ @machine.communicate.execute(<<-BASH)
15
25
  if ! (grep #{user} /etc/passwd); then
16
26
  useradd -m -s /bin/bash #{user};
17
- echo -e "#{user}\n#{user}" | (passwd #{user});
18
27
  fi
19
28
  BASH
20
29
 
21
- env[:ui].info @translator.t("sudo", :user => user)
22
- env[:machine].communicate.execute(<<-BASH)
30
+ # grant user sudo access with no password requirement
31
+ @machine.communicate.execute(<<-BASH)
23
32
  if ! (grep #{user} /etc/sudoers); then
24
- echo "#{user} ALL=(ALL:ALL) ALL" >> /etc/sudoers;
33
+ echo "#{user} ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers;
25
34
  fi
26
35
  BASH
27
36
 
28
37
  # create the .ssh directory in the users home
29
- env[:machine].communicate.execute("su #{user} -c 'mkdir -p ~/.ssh'")
38
+ @machine.communicate.execute("su #{user} -c 'mkdir -p ~/.ssh'")
30
39
 
31
- env[:ui].info @translator.t("key")
32
40
  # add the specified key to the authorized keys file
33
- env[:machine].communicate.execute(<<-BASH)
41
+ private_key_path = @machine.ssh_info()[:private_key_path]
42
+ pub_key = DigitalOcean.public_key(private_key_path)
43
+ @machine.communicate.execute(<<-BASH)
34
44
  if ! grep '#{pub_key}' /home/#{user}/.ssh/authorized_keys; then
35
45
  echo '#{pub_key}' >> /home/#{user}/.ssh/authorized_keys;
36
46
  fi
37
47
  BASH
38
48
 
39
- env[:machine_state] ||= {}
40
- env[:machine_state][:user] = user
49
+ # reset username
50
+ @machine.config.ssh.username = user
41
51
 
42
52
  @app.call(env)
43
53
  end
44
-
45
- private
46
-
47
- # TODO use a config option to allow for alternate users
48
- def user
49
- "vagrant"
50
- end
51
-
52
- # TODO allow for a custom key to specified
53
- def pub_key
54
- @key ||= DigitalOcean.vagrant_key
55
- end
56
54
  end
57
55
  end
58
56
  end
@@ -1,40 +1,39 @@
1
- require "vagrant/util/subprocess"
1
+ require 'vagrant/util/subprocess'
2
2
 
3
3
  module VagrantPlugins
4
4
  module DigitalOcean
5
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
6
  class SyncFolders
10
7
  def initialize(app, env)
11
- @app, @env = app, env
12
- @translator = Helpers::Translator.new("actions.sync_folders")
8
+ @app = app
9
+ @machine = env[:machine]
10
+ @logger = Log4r::Logger.new('vagrant::digitalocean::sync_folders')
13
11
  end
14
12
 
15
13
  def call(env)
16
- @app.call(env)
14
+ ssh_info = @machine.ssh_info
17
15
 
18
- ssh_info = env[:machine].ssh_info
16
+ @machine.config.vm.synced_folders.each do |id, data|
17
+ next if data[:disabled]
19
18
 
20
- env[:machine].config.vm.synced_folders.each do |id, data|
21
19
  hostpath = File.expand_path(data[:hostpath], env[:root_path])
22
20
  guestpath = data[:guestpath]
23
21
 
24
- # Make sure there is a trailing slash on the host path to
22
+ # make sure there is a trailing slash on the host path to
25
23
  # avoid creating an additional directory with rsync
26
24
  hostpath = "#{hostpath}/" if hostpath !~ /\/$/
27
25
 
28
- env[:ui].info @translator.t("rsync_folder",
29
- :hostpath => hostpath,
30
- :guestpath => guestpath)
26
+ env[:ui].info I18n.t('vagrant_digital_ocean.info.rsyncing', {
27
+ :hostpath => hostpath,
28
+ :guestpath => guestpath
29
+ })
31
30
 
32
- # Create the guest path
33
- env[:machine].communicate.sudo("mkdir -p #{guestpath}")
34
- env[:machine].communicate.sudo(
31
+ # create the guest path
32
+ @machine.communicate.sudo("mkdir -p #{guestpath}")
33
+ @machine.communicate.sudo(
35
34
  "chown -R #{ssh_info[:username]} #{guestpath}")
36
35
 
37
- # Rsync over to the guest path using the SSH info
36
+ # rsync over to the guest path using the ssh info
38
37
  command = [
39
38
  "rsync", "--verbose", "--archive", "-z",
40
39
  "-e", "ssh -p #{ssh_info[:port]} -o StrictHostKeyChecking=no -i '#{ssh_info[:private_key_path]}'",
@@ -49,6 +48,8 @@ module VagrantPlugins
49
48
  :stderr => r.stderr
50
49
  end
51
50
  end
51
+
52
+ @app.call(env)
52
53
  end
53
54
  end
54
55
  end
@@ -3,14 +3,13 @@ require 'optparse'
3
3
  module VagrantPlugins
4
4
  module DigitalOcean
5
5
  module Commands
6
- class Rebuild < Vagrant.plugin("2", :command)
6
+ class Rebuild < Vagrant.plugin('2', :command)
7
7
  def execute
8
8
  opts = OptionParser.new do |o|
9
- o.banner = "Usage: vagrant rebuild [vm-name]"
9
+ o.banner = 'Usage: vagrant rebuild [vm-name]'
10
10
  end
11
11
 
12
12
  argv = parse_options(opts)
13
- return if !argv
14
13
 
15
14
  with_target_vms(argv) do |machine|
16
15
  machine.action(:rebuild)
@@ -1,52 +1,49 @@
1
1
  module VagrantPlugins
2
2
  module DigitalOcean
3
- class Config < Vagrant.plugin("2", :config)
4
- attr_accessor :client_id, :api_key, :image, :region, :size, :ca_path,
5
- :ssh_key_name, :ssh_private_key_path, :ssh_username
3
+ class Config < Vagrant.plugin('2', :config)
4
+ attr_accessor :client_id
5
+ attr_accessor :api_key
6
+ attr_accessor :image
7
+ attr_accessor :region
8
+ attr_accessor :size
9
+ attr_accessor :ca_path
10
+ attr_accessor :ssh_key_name
6
11
 
7
12
  def initialize
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")
13
+ @client_id = UNSET_VALUE
14
+ @api_key = UNSET_VALUE
15
+ @image = UNSET_VALUE
16
+ @region = UNSET_VALUE
17
+ @size = UNSET_VALUE
18
+ @ca_path = UNSET_VALUE
19
+ @ssh_key_name = UNSET_VALUE
19
20
  end
20
21
 
21
22
  def finalize!
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
23
+ @client_id = ENV['DO_CLIENT_ID'] if @client_id == UNSET_VALUE
24
+ @api_key = ENV['DO_API_KEY'] if @api_key == UNSET_VALUE
25
+ @image = 'Ubuntu 12.04 x64 Server' if @image == UNSET_VALUE
26
+ @region = 'New York 1' if @region == UNSET_VALUE
27
+ @size = '512MB' if @size == UNSET_VALUE
28
+ @ca_path = nil if @ca_path == UNSET_VALUE
29
+ @ssh_key_name = 'Vagrant' if @ssh_key_name == UNSET_VALUE
31
30
  end
32
31
 
33
32
  def validate(machine)
34
33
  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
34
+ errors << I18n.t('vagrant_digital_ocean.config.client_id') if !@client_id
35
+ errors << I18n.t('vagrant_digital_ocean.config.api_key') if !@api_key
40
36
 
37
+ key = machine.config.ssh.private_key_path
41
38
  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 })
39
+ errors << I18n.t('vagrant_digital_ocean.config.private_key')
45
40
  elsif !File.file?(File.expand_path("#{key}.pub", machine.env.root_path))
46
- errors << @translator.t(:public_key_missing, { :key => key })
41
+ errors << I18n.t('vagrant_digital_ocean.config.public_key', {
42
+ :key => "#{key}.pub"
43
+ })
47
44
  end
48
45
 
49
- { "Digital Ocean Provider" => errors }
46
+ { 'Digital Ocean Provider' => errors }
50
47
  end
51
48
  end
52
49
  end
@@ -1,5 +1,3 @@
1
- require "vagrant"
2
-
3
1
  module VagrantPlugins
4
2
  module DigitalOcean
5
3
  module Errors
@@ -1,24 +1,23 @@
1
- require "vagrant-digitalocean/helpers/result"
2
- require "faraday"
3
- require "json"
1
+ require 'vagrant-digitalocean/helpers/result'
2
+ require 'faraday'
3
+ require 'json'
4
4
 
5
5
  module VagrantPlugins
6
6
  module DigitalOcean
7
7
  module Helpers
8
8
  module Client
9
9
  def client
10
- @client ||= ApiClient.new(@env)
10
+ @client ||= ApiClient.new(@machine)
11
11
  end
12
12
  end
13
13
 
14
14
  class ApiClient
15
15
  include Vagrant::Util::Retryable
16
16
 
17
- def initialize(env)
18
- @env = env
19
- @config = env[:machine].provider_config
17
+ def initialize(machine)
18
+ @config = machine.provider_config
20
19
  @client = Faraday.new({
21
- :url => "https://api.digitalocean.com/",
20
+ :url => 'https://api.digitalocean.com/',
22
21
  :ssl => {
23
22
  :ca_file => @config.ca_path
24
23
  }
@@ -43,7 +42,7 @@ module VagrantPlugins
43
42
  end
44
43
 
45
44
  # remove the api key in case an error gets dumped to the console
46
- params[:api_key] = "REMOVED"
45
+ params[:api_key] = 'REMOVED'
47
46
 
48
47
  begin
49
48
  body = JSON.parse(result.body)
@@ -56,11 +55,11 @@ module VagrantPlugins
56
55
  })
57
56
  end
58
57
 
59
- if body["status"] != "OK"
58
+ if body['status'] != 'OK'
60
59
  raise(Errors::APIStatusError, {
61
60
  :path => path,
62
61
  :params => params,
63
- :status => body["status"],
62
+ :status => body['status'],
64
63
  :response => body.inspect
65
64
  })
66
65
  end
@@ -68,17 +67,16 @@ module VagrantPlugins
68
67
  Result.new(body)
69
68
  end
70
69
 
71
- def wait_for_event(id)
70
+ def wait_for_event(env, id)
72
71
  retryable(:tries => 30, :sleep => 10) do
73
72
  # stop waiting if interrupted
74
- next if @env[:interrupted]
75
-
73
+ next if env[:interrupted]
76
74
 
77
75
  # check event status
78
76
  result = self.request("/events/#{id}")
79
77
 
80
78
  yield result if block_given?
81
- raise "not ready" if result["event"]["action_status"] != "done"
79
+ raise 'not ready' if result['event']['action_status'] != 'done'
82
80
  end
83
81
  end
84
82
  end
@@ -1,33 +1,24 @@
1
- require "i18n"
2
- require "vagrant-digitalocean/helpers/translator"
3
-
4
1
  module VagrantPlugins
5
2
  module DigitalOcean
6
- class Plugin < Vagrant.plugin("2")
7
- name "DigitalOcean"
3
+ class Plugin < Vagrant.plugin('2')
4
+ name 'DigitalOcean'
8
5
  description <<-DESC
9
6
  This plugin installs a provider that allows Vagrant to manage
10
7
  machines using DigitalOcean's API.
11
8
  DESC
12
9
 
13
10
  config(:digital_ocean, :provider) do
14
- require_relative "config"
11
+ require_relative 'config'
15
12
  Config
16
13
  end
17
14
 
18
15
  provider(:digital_ocean) do
19
- # Return the provider
20
- require_relative "provider"
21
-
22
- I18n.load_path << File.expand_path("locales/en.yml", DigitalOcean.source_root)
23
- I18n.reload!
24
- Helpers::Translator.plugin_namespace = "vagrant_digital_ocean"
25
-
16
+ require_relative 'provider'
26
17
  Provider
27
18
  end
28
19
 
29
20
  command(:rebuild) do
30
- require_relative "commands/rebuild"
21
+ require_relative 'commands/rebuild'
31
22
  Commands::Rebuild
32
23
  end
33
24
  end
@@ -1,24 +1,49 @@
1
- require "vagrant-digitalocean/action"
1
+ require 'vagrant-digitalocean/actions'
2
2
 
3
3
  module VagrantPlugins
4
4
  module DigitalOcean
5
- class Provider < Vagrant.plugin("2", :provider)
6
- # Initialize the provider to represent the given machine.
7
- #
8
- # @param [Vagrant::Machine] machine The machine that this provider
9
- # is responsible for.
5
+ class Provider < Vagrant.plugin('2', :provider)
6
+
7
+ # This class method caches status for all droplets within
8
+ # the Digital Ocean account. A specific droplet's status
9
+ # may be refreshed by passing :refresh => true as an option.
10
+ def self.droplet(machine, opts = {})
11
+ client = Helpers::ApiClient.new(machine)
12
+
13
+ # load status of droplets if it has not been done before
14
+ if !@droplets
15
+ result = client.request('/droplets')
16
+ @droplets = result['droplets']
17
+ end
18
+
19
+ if opts[:refresh] && machine.id
20
+ # refresh the droplet status for the given machine
21
+ @droplets.delete_if { |d| d['id'].to_s == machine.id }
22
+ result = client.request("/droplets/#{machine.id}")
23
+ @droplets << droplet = result['droplet']
24
+ else
25
+ # lookup droplet status for the given machine
26
+ droplet = @droplets.find { |d| d['id'].to_s == machine.id }
27
+ end
28
+
29
+ # if lookup by id failed, check for a droplet with a matching name
30
+ # and set the id to ensure vagrant stores locally
31
+ # TODO allow the user to configure this behavior
32
+ if !droplet
33
+ name = machine.config.vm.hostname || machine.name
34
+ droplet = @droplets.find { |d| d['name'] == name.to_s }
35
+ machine.id = droplet['id'].to_s if droplet
36
+ end
37
+
38
+ droplet ||= {'status' => 'not_created'}
39
+ end
40
+
10
41
  def initialize(machine)
11
42
  @machine = machine
12
- @dispatch = Action.new
13
43
  end
14
44
 
15
- # This should return an action callable for the given name.
16
- #
17
- # @param [Symbol] name Name of the action.
18
- # @return [Object] A callable action sequence object, whether it
19
- # is a proc, object, etc.
20
45
  def action(name)
21
- return @dispatch.action(name) if @dispatch.respond_to?(name)
46
+ return Actions.send(name) if Actions.respond_to?(name)
22
47
  nil
23
48
  end
24
49
 
@@ -49,38 +74,27 @@ module VagrantPlugins
49
74
  # mainly for the reason that there is no easy way to exec into an
50
75
  # `ssh` prompt with a password, whereas we can pass a private key
51
76
  # via commandline.
52
- #
53
- # @return [Hash] SSH information. For the structure of this hash
54
- # read the accompanying documentation for this method.
55
77
  def ssh_info
56
- state = @machine.action("read_state")[:machine_state]
57
-
58
- return nil if state["status"] == :not_created
78
+ droplet = Provider.droplet(@machine)
59
79
 
60
- # TODO remove when defect in vagrant chef provisioner is fixed
61
- @machine.config.ssh.username = @machine.provider_config.ssh_username
80
+ return nil if droplet['status'].to_sym != :active
62
81
 
82
+ # TODO remove config.ssh.username reference when Vagrant 1.2 is released
63
83
  return {
64
- :host => state["ip_address"],
65
- :port => "22",
66
- :username => @machine.provider_config.ssh_username,
67
- :private_key_path => @machine.provider_config.ssh_private_key_path
84
+ :host => droplet['ip_address'],
85
+ :port => '22',
86
+ :username => @machine.config.ssh.username || 'root',
87
+ :private_key_path => nil
68
88
  }
69
89
  end
70
90
 
71
91
  # This should return the state of the machine within this provider.
72
92
  # The state must be an instance of {MachineState}. Please read the
73
93
  # documentation of that class for more information.
74
- #
75
- # @return [MachineState]
76
94
  def state
77
- state_id = @machine.action("read_state")[:machine_state]["status"].to_sym
78
-
79
- # TODO provide an actual description
80
- long = short = state_id.to_s
81
-
82
- # Return the MachineState object
83
- Vagrant::MachineState.new(state_id, short, long)
95
+ state = Provider.droplet(@machine)['status'].to_sym
96
+ long = short = state.to_s
97
+ Vagrant::MachineState.new(state, short, long)
84
98
  end
85
99
  end
86
100
  end