vagrant 0.5.0 → 0.5.1

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.
@@ -45,6 +45,7 @@ module Vagrant
45
45
  def run(callable, options=nil)
46
46
  callable = Builder.new.use(callable) if callable.kind_of?(Class)
47
47
  callable = self.class.actions[callable] if callable.kind_of?(Symbol)
48
+ raise Exceptions::UncallableAction.new(callable) if !callable
48
49
 
49
50
  action_environment = Action::Environment.new(env)
50
51
  action_environment.merge!(options || {})
@@ -0,0 +1,19 @@
1
+ require 'vagrant/action/general/package'
2
+
3
+ module Vagrant
4
+ class Action
5
+ module Box
6
+ # Packages a box which has already been unpackaged (such as
7
+ # for the `vagrant box repackage` command) by leveraging the
8
+ # general packager middleware.
9
+ class Package < General::Package
10
+ # Alias instead of calling super for testability
11
+ alias_method :general_call, :call
12
+ def call(env)
13
+ env["package.directory"] = env["box"].directory
14
+ general_call(env)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -32,6 +32,7 @@ module Vagrant
32
32
  # halt - Halts the VM, attempting gracefully but then forcing
33
33
  # a restart if fails.
34
34
  halt = Builder.new do
35
+ use VM::DiscardState
35
36
  use VM::Halt
36
37
  use VM::DisableNetworks
37
38
  end
@@ -89,6 +90,7 @@ module Vagrant
89
90
  use VM::ClearForwardedPorts
90
91
  use VM::ClearSharedFolders
91
92
  use VM::Export
93
+ use VM::PackageVagrantfile
92
94
  use VM::Package
93
95
  end
94
96
 
@@ -109,6 +111,13 @@ module Vagrant
109
111
  end
110
112
 
111
113
  register :box_remove, box_remove
114
+
115
+ # box_repackage - Repackages a box.
116
+ box_repackage = Builder.new do
117
+ use Box::Package
118
+ end
119
+
120
+ register :box_repackage, box_repackage
112
121
  end
113
122
  end
114
123
  end
@@ -0,0 +1,96 @@
1
+ module Vagrant
2
+ class Action
3
+ module General
4
+ # A general packaging (tar) middleware. Given the following options,
5
+ # it will do the right thing:
6
+ #
7
+ # * package.output - The filename of the outputted package.
8
+ # * package.include - An array of files to include in the package.
9
+ # * package.directory - The directory which contains the contents to
10
+ # compress into the package.
11
+ #
12
+ # This middleware always produces the final file in the current working
13
+ # directory (FileUtils.pwd)
14
+ class Package
15
+ include Util
16
+
17
+ def initialize(app, env)
18
+ @app = app
19
+ @env = env
20
+ @env["package.output"] ||= env["config"].package.name
21
+ @env["package.include"] ||= []
22
+ end
23
+
24
+ def call(env)
25
+ @env = env
26
+
27
+ return env.error!(:package_output_exists) if File.exist?(tar_path)
28
+ return env.error!(:package_requires_directory) if !@env["package.directory"] || !File.directory?(@env["package.directory"])
29
+ return if !verify_included_files
30
+ compress
31
+
32
+ @app.call(env)
33
+
34
+ cleanup if env.error?
35
+ end
36
+
37
+ def cleanup
38
+ # Cleanup any packaged files if the packaging failed at some point.
39
+ File.delete(tar_path) if File.exist?(tar_path)
40
+ end
41
+
42
+ def verify_included_files
43
+ @env["package.include"].each do |file|
44
+ if !File.exist?(file)
45
+ @env.error!(:package_include_file_doesnt_exist, :filename => file)
46
+ return false
47
+ end
48
+ end
49
+
50
+ true
51
+ end
52
+
53
+ # This method copies the include files (passed in via command line)
54
+ # to the temporary directory so they are included in a sub-folder within
55
+ # the actual box
56
+ def copy_include_files
57
+ if @env["package.include"].length > 0
58
+ include_dir = File.join(@env["package.directory"], "include")
59
+ FileUtils.mkdir_p(include_dir)
60
+
61
+ @env["package.include"].each do |f|
62
+ @env.logger.info "Packaging additional file: #{f}"
63
+ FileUtils.cp(f, include_dir)
64
+ end
65
+ end
66
+ end
67
+
68
+ # Compress the exported file into a package
69
+ def compress
70
+ @env.logger.info "Compressing package to #{tar_path}..."
71
+ File.open(tar_path, Platform.tar_file_options) do |tar|
72
+ Archive::Tar::Minitar::Output.open(tar) do |output|
73
+ begin
74
+ current_dir = FileUtils.pwd
75
+
76
+ copy_include_files
77
+
78
+ FileUtils.cd(@env["package.directory"])
79
+ Dir.glob(File.join(".", "**", "*")).each do |entry|
80
+ Archive::Tar::Minitar.pack_file(entry, output)
81
+ end
82
+ ensure
83
+ FileUtils.cd(current_dir)
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ # Path to the final box output file
90
+ def tar_path
91
+ File.join(FileUtils.pwd, @env["package.output"])
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -10,10 +10,16 @@ module Vagrant
10
10
  end
11
11
 
12
12
  def call(env)
13
- env.logger.info "Disabling host only networks..."
13
+ logged = false
14
14
 
15
15
  env["vm"].vm.network_adapters.each do |adapter|
16
16
  next if adapter.attachment_type != :host_only
17
+
18
+ if !logged
19
+ env.logger.info "Disabling host only networks..."
20
+ logged = true
21
+ end
22
+
17
23
  adapter.enabled = false
18
24
  adapter.save
19
25
  end
@@ -0,0 +1,22 @@
1
+ module Vagrant
2
+ class Action
3
+ module VM
4
+ # Discards the saved state of the VM if its saved. If its
5
+ # not saved, does nothing.
6
+ class DiscardState
7
+ def initialize(app, env)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ if env["vm"].vm.saved?
13
+ env.logger.info "Discarding saved state of VM..."
14
+ env["vm"].vm.discard_state
15
+ end
16
+
17
+ @app.call(env)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,97 +1,21 @@
1
+ require 'vagrant/action/general/package'
2
+
1
3
  module Vagrant
2
4
  class Action
3
5
  module VM
4
- class Package
5
- include Util
6
-
7
- def initialize(app, env)
8
- @app = app
9
- @env = env
10
- @env["package.output"] ||= env["config"].package.name
11
- @env["package.include"] ||= []
12
-
13
- env.error!(:box_file_exists, :output_file => tar_path) if File.exist?(tar_path)
14
- end
15
-
6
+ # A subclass of {General::Package} which simply makes sure that
7
+ # the package directory is set to the directory which the VM
8
+ # was exported to.
9
+ class Package < General::Package
10
+ # Doing this so that we can test that the parent is properly
11
+ # called in the unit tests.
12
+ alias_method :general_call, :call
16
13
  def call(env)
17
- @env = env
18
-
19
- return env.error!(:package_requires_export) if !@env["export.temp_dir"]
20
- return if !verify_included_files
21
- compress
22
-
23
- @app.call(env)
24
-
25
- cleanup if env.error?
26
- end
27
-
28
- def cleanup
29
- # Cleanup any packaged files if the packaging failed at some point.
30
- File.delete(tar_path) if File.exist?(tar_path)
31
- end
32
-
33
- def verify_included_files
34
- @env["package.include"].each do |file|
35
- if !File.exist?(file)
36
- @env.error!(:package_include_file_doesnt_exist, :filename => file)
37
- return false
38
- end
39
- end
40
-
41
- true
42
- end
43
-
44
- # This method copies the include files (passed in via command line)
45
- # to the temporary directory so they are included in a sub-folder within
46
- # the actual box
47
- def copy_include_files
48
- if @env["package.include"].length > 0
49
- include_dir = File.join(@env["export.temp_dir"], "include")
50
- FileUtils.mkdir_p(include_dir)
51
-
52
- @env["package.include"].each do |f|
53
- @env.logger.info "Packaging additional file: #{f}"
54
- FileUtils.cp(f, include_dir)
55
- end
56
- end
57
- end
58
-
59
- # This method creates the auto-generated Vagrantfile at the root of the
60
- # box. This Vagrantfile contains the MAC address so that the user doesn't
61
- # have to worry about it.
62
- def create_vagrantfile
63
- File.open(File.join(@env["export.temp_dir"], "Vagrantfile"), "w") do |f|
64
- f.write(TemplateRenderer.render("package_Vagrantfile", {
65
- :base_mac => @env["vm"].vm.network_adapters.first.mac_address
66
- }))
67
- end
68
- end
69
-
70
- # Compress the exported file into a package
71
- def compress
72
- @env.logger.info "Packaging VM into #{tar_path}..."
73
- File.open(tar_path, Platform.tar_file_options) do |tar|
74
- Archive::Tar::Minitar::Output.open(tar) do |output|
75
- begin
76
- current_dir = FileUtils.pwd
77
-
78
- copy_include_files
79
- create_vagrantfile
80
-
81
- FileUtils.cd(@env["export.temp_dir"])
82
- Dir.glob(File.join(".", "**", "*")).each do |entry|
83
- Archive::Tar::Minitar.pack_file(entry, output)
84
- end
85
- ensure
86
- FileUtils.cd(current_dir)
87
- end
88
- end
89
- end
90
- end
91
-
92
- # Path to the final box output file
93
- def tar_path
94
- File.join(FileUtils.pwd, @env["package.output"])
14
+ # Just match up a couple environmental variables so that
15
+ # the superclass will do the right thing. Then, call the
16
+ # superclass
17
+ env["package.directory"] = env["export.temp_dir"]
18
+ general_call(env)
95
19
  end
96
20
  end
97
21
  end
@@ -0,0 +1,33 @@
1
+ module Vagrant
2
+ class Action
3
+ module VM
4
+ # Puts a generated Vagrantfile into the package directory so that
5
+ # it can be included in the package.
6
+ class PackageVagrantfile
7
+ include Util
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ @env = env
12
+ end
13
+
14
+ def call(env)
15
+ @env = env
16
+ create_vagrantfile
17
+ @app.call(env)
18
+ end
19
+
20
+ # This method creates the auto-generated Vagrantfile at the root of the
21
+ # box. This Vagrantfile contains the MAC address so that the user doesn't
22
+ # have to worry about it.
23
+ def create_vagrantfile
24
+ File.open(File.join(@env["package.directory"], "Vagrantfile"), "w") do |f|
25
+ f.write(TemplateRenderer.render("package_Vagrantfile", {
26
+ :base_mac => @env["vm"].vm.network_adapters.first.mac_address
27
+ }))
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -9,7 +9,7 @@ module Vagrant
9
9
  def call(env)
10
10
  if env["vm"].vm.saved?
11
11
  env.logger.info "Resuming suspended VM..."
12
- env["actions"].run(:start)
12
+ env["actions"].run(Boot)
13
13
  end
14
14
 
15
15
  @app.call(env)
@@ -132,11 +132,16 @@ module Vagrant
132
132
  env.actions.run(:box_add, { "box" => self })
133
133
  end
134
134
 
135
- # Beings the process of destroying this box.
135
+ # Begins the process of destroying this box.
136
136
  def destroy
137
137
  env.actions.run(:box_remove, { "box" => self })
138
138
  end
139
139
 
140
+ # Begins sequence to repackage this box.
141
+ def repackage(options=nil)
142
+ env.actions.run(:box_repackage, { "box" => self }.merge(options || {}))
143
+ end
144
+
140
145
  # Returns the directory to the location of this boxes content in the local
141
146
  # filesystem.
142
147
  #
@@ -27,4 +27,4 @@ module Vagrant
27
27
  end
28
28
  end
29
29
  end
30
- end
30
+ end
@@ -0,0 +1,35 @@
1
+ module Vagrant
2
+ class Commands
3
+ module Box
4
+ # Repackage a box which has been added.
5
+ class Repackage < BoxCommand
6
+ BoxCommand.subcommand "repackage", self
7
+ description "Repackages a box which has already been added."
8
+
9
+ def execute(args=[])
10
+ args = parse_options(args)
11
+ return show_help if args.length != 1
12
+
13
+ box = Vagrant::Box.find(env, args.first)
14
+ return error_and_exit(:box_repackage_doesnt_exist) if box.nil?
15
+ box.repackage(options)
16
+ end
17
+
18
+ def options_spec(opts)
19
+ opts.banner = "Usage: vagrant box repackage NAME [--output FILENAME] [--include FILES]"
20
+
21
+ options["package.output"] = nil
22
+ options["package.include"] = []
23
+
24
+ opts.on("--include x,y,z", Array, "List of files to include in the package") do |v|
25
+ options["package.include"] = v
26
+ end
27
+
28
+ opts.on("-o", "--output FILE", "File to save the package as.") do |v|
29
+ options["package.output"] = v
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -57,7 +57,7 @@ module Vagrant
57
57
  end
58
58
 
59
59
  def options_spec(opts)
60
- opts.banner = "Usage: vagrant package [--base BASE] [--include FILES]"
60
+ opts.banner = "Usage: vagrant package [--base BASE] [--output FILENAME] [--include FILES]"
61
61
 
62
62
  # Defaults
63
63
  options[:base] = nil
@@ -10,6 +10,7 @@ module Vagrant
10
10
  description "Reload the vagrant environment"
11
11
 
12
12
  def execute(args=[])
13
+ env.require_root_path
13
14
  all_or_single(args, :reload)
14
15
  end
15
16
 
@@ -9,6 +9,7 @@ module Vagrant
9
9
  description "Creates the vagrant environment"
10
10
 
11
11
  def execute(args=[])
12
+ env.require_root_path
12
13
  all_or_single(args, :up)
13
14
  end
14
15
 
@@ -0,0 +1,17 @@
1
+ module Vagrant
2
+ module Exceptions
3
+ # Raised when an action sequence is trying to be run for an uncallable
4
+ # action (not a lambda, middleware, or registered sequence).
5
+ class UncallableAction < ::Exception
6
+ def initialize(callable)
7
+ super()
8
+
9
+ @callable = callable
10
+ end
11
+
12
+ def to_s
13
+ @callable.inspect
14
+ end
15
+ end
16
+ end
17
+ end
@@ -40,6 +40,7 @@ module Vagrant
40
40
  end
41
41
 
42
42
  def nfs_cleanup
43
+ return if !File.exist?("/etc/exports")
43
44
  system("cat /etc/exports | grep 'VAGRANT-BEGIN: #{env.vm.uuid}' > /dev/null 2>&1")
44
45
 
45
46
  if $?.to_i == 0
@@ -39,6 +39,7 @@ module Vagrant
39
39
  end
40
40
 
41
41
  def nfs_cleanup
42
+ return if !File.exist?("/etc/exports")
42
43
  system("cat /etc/exports | grep 'VAGRANT-BEGIN: #{env.vm.uuid}' > /dev/null 2>&1")
43
44
 
44
45
  if $?.to_i == 0
@@ -16,6 +16,7 @@ module Vagrant
16
16
  # Chef solo specific config
17
17
  attr_accessor :cookbooks_path
18
18
  attr_accessor :roles_path
19
+ attr_accessor :recipe_url
19
20
 
20
21
  # Shared config
21
22
  attr_accessor :provisioning_path
@@ -27,7 +28,7 @@ module Vagrant
27
28
  @client_key_path = "/etc/chef/client.pem"
28
29
  @node_name = "client"
29
30
 
30
- @cookbooks_path = "cookbooks"
31
+ @cookbooks_path = ["cookbooks", [:vm, "cookbooks"]]
31
32
  @roles_path = []
32
33
  @provisioning_path = "/tmp/vagrant-chef"
33
34
  @log_level = :info
@@ -32,7 +32,8 @@ module Vagrant
32
32
  :node_name => env.config.chef.node_name,
33
33
  :provisioning_path => env.config.chef.provisioning_path,
34
34
  :cookbooks_path => cookbooks_path,
35
- :roles_path => roles_path
35
+ :recipe_url => env.config.chef.recipe_url,
36
+ :roles_path => roles_path,
36
37
  })
37
38
  end
38
39
 
@@ -49,23 +50,43 @@ module Vagrant
49
50
  end
50
51
 
51
52
  def host_folder_paths(paths)
52
- [paths].flatten.collect { |path| File.expand_path(path, env.root_path) }
53
+ # Convert single cookbook paths such as "cookbooks" or [:vm, "cookbooks"]
54
+ # into a proper array representation.
55
+ paths = [paths] if paths.is_a?(String) || paths.first.is_a?(Symbol)
56
+
57
+ paths.inject([]) do |acc, path|
58
+ path = [:host, path] if !path.is_a?(Array)
59
+ type, path = path
60
+
61
+ acc << File.expand_path(path, env.root_path) if type == :host
62
+ acc
63
+ end
53
64
  end
54
65
 
55
- def folder_path(folder, i)
56
- File.join(env.config.chef.provisioning_path, "#{folder}-#{i}")
66
+ def folder_path(*args)
67
+ File.expand_path(args.join("-"), env.config.chef.provisioning_path)
57
68
  end
58
69
 
59
70
  def folders_path(folders, folder)
71
+ # Convert single cookbook paths such as "cookbooks" or [:vm, "cookbooks"]
72
+ # into a proper array representation.
73
+ folders = [folders] if folders.is_a?(String) || folders.first.is_a?(Symbol)
74
+
75
+ # Convert each path to the proper absolute path depending on if the path
76
+ # is a host path or a VM path
60
77
  result = []
61
- folders.each_with_index do |host_path, i|
62
- result << folder_path(folder, i)
78
+ folders.each_with_index do |path, i|
79
+ path = [:host, path] if !path.is_a?(Array)
80
+ type, path = path
81
+
82
+ result << folder_path(folder, i) if type == :host
83
+ result << folder_path(path) if type == :vm
63
84
  end
64
85
 
65
86
  # We're lucky that ruby's string and array syntax for strings is the
66
87
  # same as JSON, so we can just convert to JSON here and use that
67
88
  result = result[0].to_s if result.length == 1
68
- result.to_json
89
+ result
69
90
  end
70
91
 
71
92
  def host_cookbook_paths
@@ -85,11 +106,11 @@ module Vagrant
85
106
  end
86
107
 
87
108
  def cookbooks_path
88
- folders_path(host_cookbook_paths, "cookbooks")
109
+ folders_path(env.config.chef.cookbooks_path, "cookbooks").to_json
89
110
  end
90
111
 
91
112
  def roles_path
92
- folders_path(host_role_paths, "roles")
113
+ folders_path(env.config.chef.roles_path, "roles").to_json
93
114
  end
94
115
  end
95
116
  end
@@ -2,5 +2,5 @@ module Vagrant
2
2
  # This will always be up to date with the current version of Vagrant,
3
3
  # since it is used to generate the gemspec and is also the source of
4
4
  # the version for `vagrant -v`
5
- VERSION = "0.5.0"
5
+ VERSION = "0.5.1"
6
6
  end
@@ -3,3 +3,7 @@ file_cache_path "<%= provisioning_path %>"
3
3
  cookbook_path <%= cookbooks_path %>
4
4
  role_path <%= roles_path %>
5
5
  log_level <%= log_level.inspect %>
6
+
7
+ <% if recipe_url %>
8
+ recipe_url "<%= recipe_url %>"
9
+ <% end %>
@@ -84,6 +84,11 @@
84
84
  Specified output file: <%= output_file %>
85
85
  :box_remove_doesnt_exist: |-
86
86
  The box you're attempting to remove does not exist!
87
+ :box_repackage_doesnt_exist: |-
88
+ The box you're attempting to repackage does not exist. Please check the
89
+ name you specified and try again. As a reminder, the repackage
90
+ command is for repackaging boxes which have been added through `vagrant box add`
91
+ but the box has been lost.
87
92
  :box_specified_doesnt_exist: |-
88
93
  Specified box `<%= box_name %>` does not exist!
89
94
 
@@ -171,6 +176,13 @@
171
176
  specific VM must be specified. This can be done by calling
172
177
  `vagrant package NAME` where NAME is a valid VM represented by
173
178
  your Vagrantfile.
179
+ :package_output_exists: |-
180
+ The specified file to save the package as already exists. Please
181
+ remove this file or specify a different filename for outputting.
182
+ :package_requires_directory: |-
183
+ A directory was not specified to package. This is an internal
184
+ issue. Please send the relevant stack trace (if any) and information
185
+ about this issue to the Vagrant team.
174
186
  :package_requires_export: |-
175
187
  Package must be used in conjunction with export.
176
188
  :provisioner_invalid_class: |-
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 9
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 5
9
- - 0
10
- version: 0.5.0
9
+ - 1
10
+ version: 0.5.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Mitchell Hashimoto
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-07-26 00:00:00 -07:00
19
+ date: 2010-07-31 00:00:00 -07:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -193,6 +193,7 @@ files:
193
193
  - lib/vagrant/action/action_exception.rb
194
194
  - lib/vagrant/action/box/destroy.rb
195
195
  - lib/vagrant/action/box/download.rb
196
+ - lib/vagrant/action/box/package.rb
196
197
  - lib/vagrant/action/box/unpackage.rb
197
198
  - lib/vagrant/action/box/verify.rb
198
199
  - lib/vagrant/action/builder.rb
@@ -201,6 +202,7 @@ files:
201
202
  - lib/vagrant/action/env/set.rb
202
203
  - lib/vagrant/action/environment.rb
203
204
  - lib/vagrant/action/exception_catcher.rb
205
+ - lib/vagrant/action/general/package.rb
204
206
  - lib/vagrant/action/vm/boot.rb
205
207
  - lib/vagrant/action/vm/check_box.rb
206
208
  - lib/vagrant/action/vm/check_guest_additions.rb
@@ -212,6 +214,7 @@ files:
212
214
  - lib/vagrant/action/vm/destroy.rb
213
215
  - lib/vagrant/action/vm/destroy_unused_network_interfaces.rb
214
216
  - lib/vagrant/action/vm/disable_networks.rb
217
+ - lib/vagrant/action/vm/discard_state.rb
215
218
  - lib/vagrant/action/vm/export.rb
216
219
  - lib/vagrant/action/vm/forward_ports.rb
217
220
  - lib/vagrant/action/vm/forward_ports_helpers.rb
@@ -222,6 +225,7 @@ files:
222
225
  - lib/vagrant/action/vm/nfs.rb
223
226
  - lib/vagrant/action/vm/nfs_helpers.rb
224
227
  - lib/vagrant/action/vm/package.rb
228
+ - lib/vagrant/action/vm/package_vagrantfile.rb
225
229
  - lib/vagrant/action/vm/persist.rb
226
230
  - lib/vagrant/action/vm/provision.rb
227
231
  - lib/vagrant/action/vm/resume.rb
@@ -235,6 +239,7 @@ files:
235
239
  - lib/vagrant/commands/box/add.rb
236
240
  - lib/vagrant/commands/box/list.rb
237
241
  - lib/vagrant/commands/box/remove.rb
242
+ - lib/vagrant/commands/box/repackage.rb
238
243
  - lib/vagrant/commands/box.rb
239
244
  - lib/vagrant/commands/destroy.rb
240
245
  - lib/vagrant/commands/halt.rb
@@ -253,6 +258,7 @@ files:
253
258
  - lib/vagrant/downloaders/file.rb
254
259
  - lib/vagrant/downloaders/http.rb
255
260
  - lib/vagrant/environment.rb
261
+ - lib/vagrant/exceptions/uncallable_action.rb
256
262
  - lib/vagrant/hosts/base.rb
257
263
  - lib/vagrant/hosts/bsd.rb
258
264
  - lib/vagrant/hosts/linux.rb