vagrant 0.3.4 → 0.4.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 (124) hide show
  1. data/Gemfile +2 -2
  2. data/README.md +2 -2
  3. data/Rakefile +1 -1
  4. data/VERSION +1 -1
  5. data/config/default.rb +13 -3
  6. data/lib/vagrant.rb +10 -13
  7. data/lib/vagrant/actions/base.rb +14 -2
  8. data/lib/vagrant/actions/box/download.rb +2 -7
  9. data/lib/vagrant/actions/box/verify.rb +1 -1
  10. data/lib/vagrant/actions/runner.rb +0 -1
  11. data/lib/vagrant/actions/vm/boot.rb +2 -6
  12. data/lib/vagrant/actions/vm/customize.rb +7 -5
  13. data/lib/vagrant/actions/vm/destroy.rb +4 -3
  14. data/lib/vagrant/actions/vm/down.rb +6 -3
  15. data/lib/vagrant/actions/vm/export.rb +2 -4
  16. data/lib/vagrant/actions/vm/forward_ports.rb +77 -16
  17. data/lib/vagrant/actions/vm/halt.rb +10 -2
  18. data/lib/vagrant/actions/vm/import.rb +2 -4
  19. data/lib/vagrant/actions/vm/move_hard_drive.rb +2 -2
  20. data/lib/vagrant/actions/vm/network.rb +120 -0
  21. data/lib/vagrant/actions/vm/package.rb +11 -7
  22. data/lib/vagrant/actions/vm/provision.rb +3 -3
  23. data/lib/vagrant/actions/vm/reload.rb +2 -9
  24. data/lib/vagrant/actions/vm/shared_folders.rb +19 -39
  25. data/lib/vagrant/actions/vm/start.rb +10 -2
  26. data/lib/vagrant/actions/vm/up.rb +5 -6
  27. data/lib/vagrant/active_list.rb +23 -13
  28. data/lib/vagrant/box.rb +2 -2
  29. data/lib/vagrant/busy.rb +3 -3
  30. data/lib/vagrant/command.rb +2 -2
  31. data/lib/vagrant/commands/base.rb +40 -20
  32. data/lib/vagrant/commands/destroy.rb +17 -3
  33. data/lib/vagrant/commands/halt.rb +23 -3
  34. data/lib/vagrant/commands/package.rb +54 -14
  35. data/lib/vagrant/commands/provision.rb +31 -0
  36. data/lib/vagrant/commands/reload.rb +16 -3
  37. data/lib/vagrant/commands/resume.rb +16 -3
  38. data/lib/vagrant/commands/ssh.rb +25 -3
  39. data/lib/vagrant/commands/ssh_config.rb +20 -5
  40. data/lib/vagrant/commands/status.rb +107 -40
  41. data/lib/vagrant/commands/suspend.rb +16 -3
  42. data/lib/vagrant/commands/up.rb +26 -7
  43. data/lib/vagrant/config.rb +82 -12
  44. data/lib/vagrant/downloaders/base.rb +8 -1
  45. data/lib/vagrant/downloaders/http.rb +31 -19
  46. data/lib/vagrant/environment.rb +146 -49
  47. data/lib/vagrant/provisioners/base.rb +19 -5
  48. data/lib/vagrant/provisioners/chef.rb +12 -4
  49. data/lib/vagrant/provisioners/chef_server.rb +13 -6
  50. data/lib/vagrant/provisioners/chef_solo.rb +7 -3
  51. data/lib/vagrant/resource_logger.rb +126 -0
  52. data/lib/vagrant/ssh.rb +109 -8
  53. data/lib/vagrant/systems/base.rb +70 -0
  54. data/lib/vagrant/systems/linux.rb +137 -0
  55. data/lib/vagrant/util.rb +1 -45
  56. data/lib/vagrant/util/error_helper.rb +13 -0
  57. data/lib/vagrant/util/glob_loader.rb +22 -0
  58. data/lib/vagrant/util/output_helper.rb +9 -0
  59. data/lib/vagrant/util/plain_logger.rb +12 -0
  60. data/lib/vagrant/util/platform.rb +7 -2
  61. data/lib/vagrant/util/template_renderer.rb +2 -2
  62. data/lib/vagrant/util/translator.rb +35 -0
  63. data/lib/vagrant/vm.rb +91 -10
  64. data/templates/crontab_entry.erb +1 -0
  65. data/templates/network_entry.erb +8 -0
  66. data/templates/ssh_config.erb +1 -0
  67. data/templates/{errors.yml → strings.yml} +111 -3
  68. data/templates/sync.erb +14 -0
  69. data/test/test_helper.rb +46 -3
  70. data/test/vagrant/actions/box/download_test.rb +0 -17
  71. data/test/vagrant/actions/vm/boot_test.rb +3 -10
  72. data/test/vagrant/actions/vm/customize_test.rb +6 -0
  73. data/test/vagrant/actions/vm/destroy_test.rb +6 -5
  74. data/test/vagrant/actions/vm/down_test.rb +5 -11
  75. data/test/vagrant/actions/vm/export_test.rb +1 -0
  76. data/test/vagrant/actions/vm/forward_ports_test.rb +92 -15
  77. data/test/vagrant/actions/vm/halt_test.rb +36 -4
  78. data/test/vagrant/actions/vm/import_test.rb +2 -0
  79. data/test/vagrant/actions/vm/network_test.rb +237 -0
  80. data/test/vagrant/actions/vm/package_test.rb +35 -5
  81. data/test/vagrant/actions/vm/provision_test.rb +3 -3
  82. data/test/vagrant/actions/vm/reload_test.rb +1 -1
  83. data/test/vagrant/actions/vm/shared_folders_test.rb +41 -74
  84. data/test/vagrant/actions/vm/start_test.rb +41 -3
  85. data/test/vagrant/actions/vm/up_test.rb +10 -21
  86. data/test/vagrant/active_list_test.rb +28 -43
  87. data/test/vagrant/commands/base_test.rb +25 -4
  88. data/test/vagrant/commands/destroy_test.rb +24 -12
  89. data/test/vagrant/commands/halt_test.rb +33 -11
  90. data/test/vagrant/commands/package_test.rb +77 -57
  91. data/test/vagrant/commands/provision_test.rb +50 -0
  92. data/test/vagrant/commands/reload_test.rb +27 -11
  93. data/test/vagrant/commands/resume_test.rb +25 -14
  94. data/test/vagrant/commands/ssh_config_test.rb +40 -17
  95. data/test/vagrant/commands/ssh_test.rb +52 -13
  96. data/test/vagrant/commands/status_test.rb +21 -1
  97. data/test/vagrant/commands/suspend_test.rb +25 -14
  98. data/test/vagrant/commands/up_test.rb +25 -19
  99. data/test/vagrant/config_test.rb +74 -18
  100. data/test/vagrant/downloaders/base_test.rb +2 -1
  101. data/test/vagrant/downloaders/http_test.rb +18 -8
  102. data/test/vagrant/environment_test.rb +245 -77
  103. data/test/vagrant/provisioners/base_test.rb +4 -4
  104. data/test/vagrant/provisioners/chef_server_test.rb +18 -7
  105. data/test/vagrant/provisioners/chef_solo_test.rb +17 -7
  106. data/test/vagrant/provisioners/chef_test.rb +22 -9
  107. data/test/vagrant/resource_logger_test.rb +144 -0
  108. data/test/vagrant/ssh_session_test.rb +46 -0
  109. data/test/vagrant/ssh_test.rb +42 -2
  110. data/test/vagrant/systems/linux_test.rb +174 -0
  111. data/test/vagrant/util/error_helper_test.rb +5 -0
  112. data/test/vagrant/util/output_helper_test.rb +5 -0
  113. data/test/vagrant/util/plain_logger_test.rb +17 -0
  114. data/test/vagrant/util/platform_test.rb +18 -0
  115. data/test/vagrant/util/{errors_test.rb → translator_test.rb} +25 -21
  116. data/test/vagrant/util_test.rb +12 -49
  117. data/test/vagrant/vm_test.rb +133 -11
  118. data/vagrant.gemspec +39 -15
  119. metadata +64 -40
  120. data/lib/vagrant/commands/down.rb +0 -16
  121. data/lib/vagrant/util/errors.rb +0 -36
  122. data/lib/vagrant/util/progress_meter.rb +0 -33
  123. data/test/vagrant/commands/down_test.rb +0 -17
  124. data/test/vagrant/util/progress_meter_test.rb +0 -33
@@ -2,18 +2,16 @@ module Vagrant
2
2
  module Actions
3
3
  module VM
4
4
  class Import < Base
5
- include Util::ProgressMeter
6
-
7
5
  def execute!
8
6
  @runner.invoke_around_callback(:import) do
9
7
  Busy.busy do
10
8
  logger.info "Importing base VM (#{@runner.env.box.ovf_file})..."
11
9
  # Use the first argument passed to the action
12
10
  @runner.vm = VirtualBox::VM.import(@runner.env.box.ovf_file) do |progress|
13
- update_progress(progress.percent, 100, false)
11
+ logger.report_progress(progress.percent, 100, false)
14
12
  end
15
13
 
16
- complete_progress
14
+ logger.clear_progress
17
15
 
18
16
  raise ActionException.new(:virtualbox_import_failure) unless @runner.vm
19
17
  end
@@ -26,7 +26,7 @@ module Vagrant
26
26
 
27
27
  def clone_and_attach
28
28
  logger.info "Cloning current VM Disk to new location (#{new_image_path})..."
29
- hard_drive.image = hard_drive.image.clone(new_image_path, Vagrant.config.vm.disk_image_format, true)
29
+ hard_drive.image = hard_drive.image.clone(new_image_path, @runner.env.config.vm.disk_image_format, true)
30
30
 
31
31
  logger.info "Attaching new disk to VM ..."
32
32
  @runner.vm.save
@@ -43,7 +43,7 @@ module Vagrant
43
43
 
44
44
  # Returns the path to the new location for the hard drive
45
45
  def new_image_path
46
- File.join(Vagrant.config.vm.hd_location, hard_drive.image.filename)
46
+ File.join(@runner.env.config.vm.hd_location, hard_drive.image.filename)
47
47
  end
48
48
  end
49
49
  end
@@ -0,0 +1,120 @@
1
+ module Vagrant
2
+ module Actions
3
+ module VM
4
+ class Network < Base
5
+ def before_destroy
6
+ # We need to check if the host only network specified by any
7
+ # of the adapters would not have any more clients if it was
8
+ # destroyed. And if so, then destroy the host only network
9
+ # itself.
10
+ interfaces = runner.vm.network_adapters.collect do |adapter|
11
+ adapter.host_interface_object
12
+ end
13
+
14
+ interfaces.compact.uniq.each do |interface|
15
+ # Destroy the network interface if there is only one
16
+ # attached VM (which must be this VM)
17
+ if interface.attached_vms.length == 1
18
+ logger.info "Destroying unused network interface..."
19
+ interface.destroy
20
+ end
21
+ end
22
+ end
23
+
24
+ def before_boot
25
+ assign_network if enable_network?
26
+ end
27
+
28
+ def after_boot
29
+ if enable_network?
30
+ logger.info "Enabling host only network..."
31
+
32
+ runner.system.prepare_host_only_network
33
+
34
+ runner.env.config.vm.network_options.compact.each do |network_options|
35
+ runner.system.enable_host_only_network(network_options)
36
+ end
37
+ end
38
+ end
39
+
40
+ def enable_network?
41
+ !runner.env.config.vm.network_options.compact.empty?
42
+ end
43
+
44
+ # Enables and assigns the host only network to the proper
45
+ # adapter on the VM, and saves the adapter.
46
+ def assign_network
47
+ logger.info "Preparing host only network..."
48
+
49
+ runner.env.config.vm.network_options.compact.each do |network_options|
50
+ adapter = runner.vm.network_adapters[network_options[:adapter]]
51
+ adapter.enabled = true
52
+ adapter.attachment_type = :host_only
53
+ adapter.host_interface = network_name(network_options)
54
+ adapter.save
55
+ end
56
+ end
57
+
58
+ # Returns the name of the proper host only network, or creates
59
+ # it if it does not exist. Vagrant determines if the host only
60
+ # network exists by comparing the netmask and the IP.
61
+ def network_name(net_options)
62
+ # First try to find a matching network
63
+ interfaces = VirtualBox::Global.global.host.network_interfaces
64
+ interfaces.each do |ni|
65
+ if net_options[:name]
66
+ return ni.name if net_options[:name] == ni.name
67
+ else
68
+ return ni.name if matching_network?(ni, net_options)
69
+ end
70
+ end
71
+
72
+ raise ActionException.new(:network_not_found, :name => net_options[:name]) if net_options[:name]
73
+
74
+ # One doesn't exist, create it.
75
+ logger.info "Creating new host only network for environment..."
76
+
77
+ ni = interfaces.create
78
+ ni.enable_static(network_ip(net_options[:ip], net_options[:netmask]),
79
+ net_options[:netmask])
80
+ ni.name
81
+ end
82
+
83
+ # Tests if a network matches the given options by applying the
84
+ # netmask to the IP of the network and also to the IP of the
85
+ # virtual machine and see if they match.
86
+ def matching_network?(interface, net_options)
87
+ interface.network_mask == net_options[:netmask] &&
88
+ apply_netmask(interface.ip_address, interface.network_mask) ==
89
+ apply_netmask(net_options[:ip], net_options[:netmask])
90
+ end
91
+
92
+ # Applies a netmask to an IP and returns the corresponding
93
+ # parts.
94
+ def apply_netmask(ip, netmask)
95
+ ip = split_ip(ip)
96
+ netmask = split_ip(netmask)
97
+
98
+ ip.map do |part|
99
+ part & netmask.shift
100
+ end
101
+ end
102
+
103
+ # Splits an IP and converts each portion into an int.
104
+ def split_ip(ip)
105
+ ip.split(".").map do |i|
106
+ i.to_i
107
+ end
108
+ end
109
+
110
+ # Returns a "network IP" which is a "good choice" for the IP
111
+ # for the actual network based on the netmask.
112
+ def network_ip(ip, netmask)
113
+ parts = apply_netmask(ip, netmask)
114
+ parts[3] += 1;
115
+ parts.join(".")
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -2,20 +2,16 @@ module Vagrant
2
2
  module Actions
3
3
  module VM
4
4
  class Package < Base
5
- attr_accessor :out_path
6
- attr_accessor :include_files
7
5
  attr_reader :export_action
8
6
 
9
- def initialize(vm, out_path = nil, include_files = nil, *args)
7
+ def initialize(*args)
10
8
  super
11
- @out_path = out_path || "package"
12
- @include_files = include_files || []
13
9
  @temp_path = nil
14
10
  end
15
11
 
16
12
  def prepare
17
13
  # Verify the existance of all the additional files, if any
18
- @include_files.each do |file|
14
+ include_files.each do |file|
19
15
  raise ActionException.new(:package_include_file_doesnt_exist, :filename => file) unless File.exists?(file)
20
16
  end
21
17
 
@@ -28,6 +24,14 @@ module Vagrant
28
24
  compress
29
25
  end
30
26
 
27
+ def out_path
28
+ options[:output] || "package"
29
+ end
30
+
31
+ def include_files
32
+ options[:include] || []
33
+ end
34
+
31
35
  def tar_path
32
36
  File.join(FileUtils.pwd, "#{out_path}#{@runner.env.config.package.extension}")
33
37
  end
@@ -64,7 +68,7 @@ module Vagrant
64
68
 
65
69
  def compress
66
70
  logger.info "Packaging VM into #{tar_path}..."
67
- File.open(tar_path, File::CREAT | File::WRONLY, 0644) do |tar|
71
+ File.open(tar_path, Platform.tar_file_options) do |tar|
68
72
  Archive::Tar::Minitar::Output.open(tar) do |output|
69
73
  begin
70
74
  current_dir = FileUtils.pwd
@@ -11,7 +11,7 @@ module Vagrant
11
11
  end
12
12
 
13
13
  def prepare
14
- provisioner = Vagrant.config.vm.provisioner
14
+ provisioner = @runner.env.config.vm.provisioner
15
15
 
16
16
  if provisioner.nil?
17
17
  logger.info("Provisioning not enabled, ignoring this step")
@@ -19,7 +19,7 @@ module Vagrant
19
19
  end
20
20
 
21
21
  if provisioner.is_a?(Class)
22
- @provisioner = provisioner.new(@runner.env)
22
+ @provisioner = provisioner.new(@runner)
23
23
  raise ActionException.new(:provisioner_invalid_class) unless @provisioner.is_a?(Provisioners::Base)
24
24
  elsif provisioner.is_a?(Symbol)
25
25
  # We have a few hard coded provisioners for built-ins
@@ -30,7 +30,7 @@ module Vagrant
30
30
 
31
31
  provisioner_klass = mapping[provisioner]
32
32
  raise ActionException.new(:provisioner_unknown_type, :provisioner => provisioner.to_s) if provisioner_klass.nil?
33
- @provisioner = provisioner_klass.new(@runner.env)
33
+ @provisioner = provisioner_klass.new(@runner)
34
34
  end
35
35
 
36
36
  logger.info "Provisioning enabled with #{@provisioner.class}"
@@ -3,7 +3,7 @@ module Vagrant
3
3
  module VM
4
4
  class Reload < Base
5
5
  def prepare
6
- steps = [Customize, ForwardPorts, SharedFolders, Boot]
6
+ steps = [Customize, ForwardPorts, SharedFolders, Network, Boot]
7
7
  steps.unshift(Halt) if @runner.vm.running?
8
8
  steps << Provision if !@runner.env.config.vm.provisioner.nil?
9
9
 
@@ -11,14 +11,7 @@ module Vagrant
11
11
  @runner.add_action(action_klass)
12
12
  end
13
13
  end
14
-
15
- def after_halt
16
- # This sleep is here to allow the VM to clean itself up. There appears
17
- # nothing [obvious] in the VirtualBox API to automate this. For now, this
18
- # is an interim solution.
19
- sleep 1
20
- end
21
14
  end
22
15
  end
23
16
  end
24
- end
17
+ end
@@ -5,7 +5,7 @@ module Vagrant
5
5
  def shared_folders
6
6
  @runner.env.config.vm.shared_folders.inject([]) do |acc, data|
7
7
  name, value = data
8
- acc << [name, File.expand_path(value[:hostpath]), value[:guestpath]]
8
+ acc << [name, File.expand_path(value[:hostpath], @runner.env.root_path), value[:guestpath], value[:syncpath]].compact
9
9
  end
10
10
  end
11
11
 
@@ -17,24 +17,30 @@ module Vagrant
17
17
  def after_boot
18
18
  logger.info "Mounting shared folders..."
19
19
 
20
- @runner.env.ssh.execute do |ssh|
21
- shared_folders.each do |name, hostpath, guestpath|
22
- logger.info "-- #{name}: #{guestpath}"
23
- ssh.exec!("sudo mkdir -p #{guestpath}")
24
- mount_folder(ssh, name, guestpath)
25
- ssh.exec!("sudo chown #{Vagrant.config.ssh.username} #{guestpath}")
20
+ @runner.ssh.execute do |ssh|
21
+ @runner.system.prepare_sync(ssh) if @runner.env.config.vm.sync_required
22
+
23
+ shared_folders.each do |name, hostpath, guestpath, syncpath|
24
+ logger.info "-- #{name}: #{syncpath ? guestpath + " -sync-> " + syncpath : guestpath}"
25
+ @runner.system.mount_shared_folder(ssh, name, guestpath)
26
+ if syncpath
27
+ @runner.system.create_sync(ssh, :syncpath => syncpath, :guestpath => guestpath)
28
+ end
26
29
  end
27
30
  end
28
31
  end
29
32
 
30
33
  def clear_shared_folders
31
- logger.info "Clearing previously set shared folders..."
34
+ if runner.vm.shared_folders.length > 0
35
+ logger.info "Clearing previously set shared folders..."
32
36
 
33
- @runner.vm.shared_folders.each do |shared_folder|
34
- shared_folder.destroy
35
- end
37
+ folders = @runner.vm.shared_folders.dup
38
+ folders.each do |shared_folder|
39
+ shared_folder.destroy
40
+ end
36
41
 
37
- @runner.reload!
42
+ @runner.reload!
43
+ end
38
44
  end
39
45
 
40
46
  def create_metadata
@@ -49,33 +55,7 @@ module Vagrant
49
55
 
50
56
  @runner.vm.save
51
57
  end
52
-
53
- def mount_folder(ssh, name, guestpath, sleeptime=5)
54
- # Note: This method seems pretty OS-specific and could also use
55
- # some configuration options. For now its duct tape and "works"
56
- # but should be looked at in the future.
57
-
58
- # Determine the permission string to attach to the mount command
59
- perms = []
60
- perms << "uid=#{@runner.env.config.vm.shared_folder_uid}"
61
- perms << "gid=#{@runner.env.config.vm.shared_folder_gid}"
62
- perms = " -o #{perms.join(",")}" if !perms.empty?
63
-
64
- attempts = 0
65
- while true
66
- result = ssh.exec!("sudo mount -t vboxsf#{perms} #{name} #{guestpath}") do |ch, type, data|
67
- # net/ssh returns the value in ch[:result] (based on looking at source)
68
- ch[:result] = !!(type == :stderr && data =~ /No such device/i)
69
- end
70
-
71
- break unless result
72
-
73
- attempts += 1
74
- raise ActionException.new(:vm_mount_fail) if attempts >= 10
75
- sleep sleeptime
76
- end
77
- end
78
58
  end
79
59
  end
80
60
  end
81
- end
61
+ end
@@ -6,12 +6,20 @@ module Vagrant
6
6
  # Start is a "meta-action" so it really just queues up a bunch
7
7
  # of other actions in its place:
8
8
  steps = [Boot]
9
- steps.unshift([Customize, ForwardPorts, SharedFolders]) unless @runner.vm.saved?
9
+ if !@runner.vm || !@runner.vm.saved?
10
+ steps.unshift([Customize, ForwardPorts, SharedFolders, Network])
11
+ steps << Provision if provision?
12
+ end
10
13
 
11
14
  steps.flatten.each do |action_klass|
12
- @runner.add_action(action_klass)
15
+ @runner.add_action(action_klass, options)
13
16
  end
14
17
  end
18
+
19
+ def provision?
20
+ enabled = options[:provision].nil? ? true : options[:provision]
21
+ !@runner.env.config.vm.provisioner.nil? && enabled
22
+ end
15
23
  end
16
24
  end
17
25
  end
@@ -10,23 +10,22 @@ module Vagrant
10
10
 
11
11
  # Up is a "meta-action" so it really just queues up a bunch
12
12
  # of other actions in its place:
13
- steps = [Import, Customize, ForwardPorts, SharedFolders, Boot]
14
- steps << Provision if !@runner.env.config.vm.provisioner.nil?
13
+ steps = [Import, Start]
15
14
  steps.insert(0, MoveHardDrive) if @runner.env.config.vm.hd_location
16
15
 
17
16
  steps.each do |action_klass|
18
- @runner.add_action(action_klass)
17
+ @runner.add_action(action_klass, options)
19
18
  end
20
19
  end
21
20
 
22
21
  def after_import
23
- persist
22
+ update_dotfile
24
23
  setup_mac_address
25
24
  end
26
25
 
27
- def persist
26
+ def update_dotfile
28
27
  logger.info "Persisting the VM UUID (#{@runner.uuid})..."
29
- @runner.env.persist_vm
28
+ @runner.env.update_dotfile
30
29
  end
31
30
 
32
31
  def setup_mac_address
@@ -23,30 +23,40 @@ module Vagrant
23
23
  def list(reload=false)
24
24
  return @list unless @list.nil? || reload
25
25
 
26
- @list ||= []
26
+ @list ||= {}
27
27
  return @list unless File.file?(path)
28
28
  File.open(path, "r") do |f|
29
- @list = JSON.parse(f.read)
29
+ begin
30
+ @list = JSON.parse(f.read)
31
+ rescue Exception
32
+ @list = {}
33
+ end
34
+
35
+ # This forces earlier versions of Vagrant to use the new hash
36
+ # format. Clearing out the old data isn't a big deal since it
37
+ # was never used.
38
+ @list = {} unless @list.is_a?(Hash)
30
39
  end
31
40
 
32
41
  @list
33
42
  end
34
43
 
35
- # Returns an array of {Vagrant::VM} objects which are currently
36
- # active.
37
- def vms
38
- list.collect { |uuid| Vagrant::VM.find(uuid) }.compact
39
- end
40
-
41
44
  # Returns an array of UUIDs filtered so each is verified to exist.
42
- def filtered_list
43
- vms.collect { |vm| vm.uuid }
45
+ def filter_list
46
+ list.each do |uuid, data|
47
+ list.delete(uuid) unless Vagrant::VM.find(uuid, env)
48
+ end
49
+
50
+ list
44
51
  end
45
52
 
46
53
  # Adds a virtual environment to the list of active virtual machines
47
54
  def add(vm)
48
- list << vm.uuid
49
- list.uniq!
55
+ list[vm.uuid] = {
56
+ :path => env.root_path,
57
+ :created_at => Time.now.to_i
58
+ }
59
+
50
60
  save
51
61
  end
52
62
 
@@ -60,7 +70,7 @@ module Vagrant
60
70
  # Persists the list down to the JSON file.
61
71
  def save
62
72
  File.open(path, "w+") do |f|
63
- f.write(filtered_list.to_json)
73
+ f.write(filter_list.to_json)
64
74
  end
65
75
  end
66
76