diff --git a/lib/vagrant/action/vm/boot.rb b/lib/vagrant/action/vm/boot.rb deleted file mode 100644 index 6a2ce7d35..000000000 --- a/lib/vagrant/action/vm/boot.rb +++ /dev/null @@ -1,53 +0,0 @@ -module Vagrant - module Action - module VM - class Boot - def initialize(app, env) - @app = app - @env = env - end - - def call(env) - @env = env - - # Start up the VM and wait for it to boot. - boot - raise Errors::VMFailedToBoot if !wait_for_boot - - @app.call(env) - end - - def boot - @env[:ui].info I18n.t("vagrant.actions.vm.boot.booting") - @env[:vm].driver.start(@env[:vm].config.vm.boot_mode) - end - - def wait_for_boot - @env[:ui].info I18n.t("vagrant.actions.vm.boot.waiting") - - @env[:vm].config.ssh.max_tries.to_i.times do |i| - if @env[:vm].channel.ready? - @env[:ui].info I18n.t("vagrant.actions.vm.boot.ready") - return true - end - - # Return true so that the vm_failed_to_boot error doesn't - # get shown - return true if @env[:interrupted] - - # If the VM is not starting or running, something went wrong - # and we need to show a useful error. - state = @env[:vm].state - raise Errors::VMFailedToRun if state != :starting && state != :running - - sleep 2 if !@env["vagrant.test"] - end - - @env[:ui].error I18n.t("vagrant.actions.vm.boot.failed") - false - end - end - end - end -end - diff --git a/lib/vagrant/action/vm/check_box.rb b/lib/vagrant/action/vm/check_box.rb deleted file mode 100644 index 454f8b492..000000000 --- a/lib/vagrant/action/vm/check_box.rb +++ /dev/null @@ -1,33 +0,0 @@ -module Vagrant - module Action - module VM - class CheckBox - def initialize(app, env) - @app = app - end - - def call(env) - box_name = env[:vm].config.vm.box - raise Errors::BoxNotSpecified if !box_name - - if !env[:box_collection].find(box_name, :virtualbox) - box_url = env[:vm].config.vm.box_url - raise Errors::BoxSpecifiedDoesntExist, :name => box_name if !box_url - - # Add the box then reload the box collection so that it becomes - # aware of it. - env[:ui].info I18n.t("vagrant.actions.vm.check_box.not_found", :name => box_name) - env[:box_collection].add(box_name, box_url) - env[:box_collection].reload! - - # Reload the environment and set the VM to be the new loaded VM. - env[:vm].env.reload! - env[:vm] = env[:vm].env.vms[env[:vm].name] - end - - @app.call(env) - end - end - end - end -end diff --git a/lib/vagrant/action/vm/check_guest_additions.rb b/lib/vagrant/action/vm/check_guest_additions.rb deleted file mode 100644 index fb96a5e65..000000000 --- a/lib/vagrant/action/vm/check_guest_additions.rb +++ /dev/null @@ -1,38 +0,0 @@ -module Vagrant - module Action - module VM - # Middleware which verifies that the VM has the proper guest additions - # installed and prints a warning if they're not detected or if the - # version does not match the installed VirtualBox version. - class CheckGuestAdditions - def initialize(app, env) - @app = app - end - - def call(env) - # Use the raw interface for now, while the virtualbox gem - # doesn't support guest properties (due to cross platform issues) - version = env[:vm].driver.read_guest_additions_version - if !version - env[:ui].warn I18n.t("vagrant.actions.vm.check_guest_additions.not_detected") - else - # Strip the -OSE/_OSE off from the guest additions and the virtual box - # version since all the matters are that the version _numbers_ match up. - guest_version, vb_version = [version, env[:vm].driver.version].map do |v| - v.gsub(/[-_]ose/i, '') - end - - if guest_version != vb_version - env[:ui].warn(I18n.t("vagrant.actions.vm.check_guest_additions.version_mismatch", - :guest_version => version, - :virtualbox_version => vb_version)) - end - end - - # Continue - @app.call(env) - end - end - end - end -end diff --git a/lib/vagrant/action/vm/check_port_collisions.rb b/lib/vagrant/action/vm/check_port_collisions.rb deleted file mode 100644 index 254b351ad..000000000 --- a/lib/vagrant/action/vm/check_port_collisions.rb +++ /dev/null @@ -1,89 +0,0 @@ -require "vagrant/util/is_port_open" - -module Vagrant - module Action - module VM - # Action that checks to make sure there are no forwarded port collisions, - # and raises an exception if there is. - class CheckPortCollisions - include Util::IsPortOpen - - def initialize(app, env) - @app = app - end - - def call(env) - # For the handlers... - @env = env - - # Figure out how we handle port collisions. By default we error. - handler = env[:port_collision_handler] || :error - - # Read our forwarded ports, if we have any, to override what - # we have configured. - current = {} - env[:vm].driver.read_forwarded_ports.each do |nic, name, hostport, guestport| - current[name] = hostport.to_i - end - - existing = env[:vm].driver.read_used_ports - env[:vm].config.vm.forwarded_ports.each do |options| - # Use the proper port, whether that be the configured port or the - # port that is currently on use of the VM. - hostport = options[:hostport].to_i - hostport = current[options[:name]] if current.has_key?(options[:name]) - - if existing.include?(hostport) || is_port_open?("localhost", hostport) - # We have a collision! Handle it - send("handle_#{handler}".to_sym, options, existing) - end - end - - @app.call(env) - end - - # Handles a port collision by raising an exception. - def handle_error(options, existing_ports) - raise Errors::ForwardPortCollisionResume - end - - # Handles a port collision by attempting to fix it. - def handle_correct(options, existing_ports) - # We need to keep this for messaging purposes - original_hostport = options[:hostport] - - if !options[:auto] - # Auto fixing is disabled for this port forward, so we - # must throw an error so the user can fix it. - raise Errors::ForwardPortCollision, :host_port => options[:hostport].to_s, - :guest_port => options[:guestport].to_s - end - - # Get the auto port range and get rid of the used ports and - # ports which are being used in other forwards so we're just - # left with available ports. - range = @env[:vm].config.vm.auto_port_range.to_a - range -= @env[:vm].config.vm.forwarded_ports.collect { |opts| opts[:hostport].to_i } - range -= existing_ports - - if range.empty? - raise Errors::ForwardPortAutolistEmpty, :vm_name => @env[:vm].name, - :host_port => options[:hostport].to_s, - :guest_port => options[:guestport].to_s - end - - # Set the port up to be the first one and add that port to - # the used list. - options[:hostport] = range.shift - existing_ports << options[:hostport] - - # Notify the user - @env[:ui].info(I18n.t("vagrant.actions.vm.forward_ports.fixed_collision", - :host_port => original_hostport.to_s, - :guest_port => options[:guestport].to_s, - :new_port => options[:hostport])) - end - end - end - end -end diff --git a/lib/vagrant/action/vm/clean_machine_folder.rb b/lib/vagrant/action/vm/clean_machine_folder.rb deleted file mode 100644 index 66c522342..000000000 --- a/lib/vagrant/action/vm/clean_machine_folder.rb +++ /dev/null @@ -1,43 +0,0 @@ -require 'fileutils' - -module Vagrant - module Action - module VM - # Cleans up the VirtualBox machine folder for any ".xml-prev" - # files which VirtualBox may have left over. This is a bug in - # VirtualBox. As soon as this is fixed, this middleware can and - # will be removed. - class CleanMachineFolder - def initialize(app, env) - @app = app - end - - def call(env) - clean_machine_folder(env[:vm].driver.read_machine_folder) - @app.call(env) - end - - def clean_machine_folder(machine_folder) - folder = File.join(machine_folder, "*") - - # Small safeguard against potentially unwanted rm-rf, since the default - # machine folder will typically always be greater than 10 characters long. - # For users with it < 10, out of luck? - return if folder.length < 10 - - Dir[folder].each do |f| - next unless File.directory?(f) - - keep = Dir["#{f}/**/*"].find do |d| - # Find a file that doesn't have ".xml-prev" as the suffix, - # which signals that we want to keep this folder - File.file?(d) && !(File.basename(d) =~ /\.vbox-prev$/) - end - - FileUtils.rm_rf(f) if !keep - end - end - end - end - end -end diff --git a/lib/vagrant/action/vm/clear_forwarded_ports.rb b/lib/vagrant/action/vm/clear_forwarded_ports.rb deleted file mode 100644 index cf25df861..000000000 --- a/lib/vagrant/action/vm/clear_forwarded_ports.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Vagrant - module Action - module VM - class ClearForwardedPorts - def initialize(app, env) - @app = app - end - - def call(env) - env[:ui].info I18n.t("vagrant.actions.vm.clear_forward_ports.deleting") - env[:vm].driver.clear_forwarded_ports - - @app.call(env) - end - end - end - end -end diff --git a/lib/vagrant/action/vm/clear_network_interfaces.rb b/lib/vagrant/action/vm/clear_network_interfaces.rb deleted file mode 100644 index 8d27a5d22..000000000 --- a/lib/vagrant/action/vm/clear_network_interfaces.rb +++ /dev/null @@ -1,31 +0,0 @@ -module Vagrant - module Action - module VM - class ClearNetworkInterfaces - def initialize(app, env) - @app = app - end - - def call(env) - # Create the adapters array to make all adapters nothing. - # We do adapters 2 to 8 because that is every built-in adapter - # excluding the NAT adapter on port 1 which Vagrant always - # expects to exist. - adapters = [] - 2.upto(8).each do |i| - adapters << { - :adapter => i, - :type => :none - } - end - - # "Enable" all the adapters we setup. - env[:ui].info I18n.t("vagrant.actions.vm.clear_network_interfaces.deleting") - env[:vm].driver.enable_adapters(adapters) - - @app.call(env) - end - end - end - end -end diff --git a/lib/vagrant/action/vm/clear_shared_folders.rb b/lib/vagrant/action/vm/clear_shared_folders.rb deleted file mode 100644 index 7ebeee543..000000000 --- a/lib/vagrant/action/vm/clear_shared_folders.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Vagrant - module Action - module VM - class ClearSharedFolders - def initialize(app, env) - @app = app - @env = env - end - - def call(env) - env[:vm].driver.clear_shared_folders - - @app.call(env) - end - end - end - end -end diff --git a/lib/vagrant/action/vm/customize.rb b/lib/vagrant/action/vm/customize.rb deleted file mode 100644 index a8696ec91..000000000 --- a/lib/vagrant/action/vm/customize.rb +++ /dev/null @@ -1,36 +0,0 @@ -module Vagrant - module Action - module VM - class Customize - def initialize(app, env) - @app = app - end - - def call(env) - customizations = env[:vm].config.vm.customizations - if !customizations.empty? - env[:ui].info I18n.t("vagrant.actions.vm.customize.running") - - # Execute each customization command. - customizations.each do |command| - processed_command = command.collect do |arg| - arg = env[:vm].uuid if arg == :id - arg.to_s - end - - result = env[:vm].driver.execute_command(processed_command) - if result.exit_code != 0 - raise Errors::VMCustomizationFailed, { - :command => processed_command.inspect, - :error => result.stderr - } - end - end - end - - @app.call(env) - end - end - end - end -end diff --git a/lib/vagrant/action/vm/default_name.rb b/lib/vagrant/action/vm/default_name.rb deleted file mode 100644 index 3ae69851d..000000000 --- a/lib/vagrant/action/vm/default_name.rb +++ /dev/null @@ -1,22 +0,0 @@ -require 'log4r' - -module Vagrant - module Action - module VM - class DefaultName - def initialize(app, env) - @logger = Log4r::Logger.new("vagrant::action::vm::defaultname") - @app = app - end - - def call(env) - @logger.info("Setting the default name of the VM") - name = env[:root_path].basename.to_s + "_#{Time.now.to_i}" - env[:vm].driver.set_name(name) - - @app.call(env) - end - end - end - end -end diff --git a/lib/vagrant/action/vm/destroy.rb b/lib/vagrant/action/vm/destroy.rb deleted file mode 100644 index 2af9b0a18..000000000 --- a/lib/vagrant/action/vm/destroy.rb +++ /dev/null @@ -1,19 +0,0 @@ -module Vagrant - module Action - module VM - class Destroy - def initialize(app, env) - @app = app - end - - def call(env) - env[:ui].info I18n.t("vagrant.actions.vm.destroy.destroying") - env[:vm].driver.delete - env[:vm].uuid = nil - - @app.call(env) - end - end - end - end -end diff --git a/lib/vagrant/action/vm/destroy_unused_network_interfaces.rb b/lib/vagrant/action/vm/destroy_unused_network_interfaces.rb deleted file mode 100644 index a0fb94c8b..000000000 --- a/lib/vagrant/action/vm/destroy_unused_network_interfaces.rb +++ /dev/null @@ -1,20 +0,0 @@ -module Vagrant - module Action - module VM - # Destroys the unused host only interfaces. This middleware cleans - # up any created host only networks. - class DestroyUnusedNetworkInterfaces - def initialize(app, env) - @app = app - end - - def call(env) - env[:vm].driver.delete_unused_host_only_networks - - # Continue along - @app.call(env) - end - end - end - end -end diff --git a/lib/vagrant/action/vm/discard_state.rb b/lib/vagrant/action/vm/discard_state.rb deleted file mode 100644 index 408b4580f..000000000 --- a/lib/vagrant/action/vm/discard_state.rb +++ /dev/null @@ -1,22 +0,0 @@ -module Vagrant - module Action - module VM - # Discards the saved state of the VM if its saved. If its - # not saved, does nothing. - class DiscardState - def initialize(app, env) - @app = app - end - - def call(env) - if env[:vm].state == :saved - env[:ui].info I18n.t("vagrant.actions.vm.discard_state.discarding") - env[:vm].driver.discard_saved_state - end - - @app.call(env) - end - end - end - end -end diff --git a/lib/vagrant/action/vm/forward_ports.rb b/lib/vagrant/action/vm/forward_ports.rb deleted file mode 100644 index 59c5d2a3f..000000000 --- a/lib/vagrant/action/vm/forward_ports.rb +++ /dev/null @@ -1,92 +0,0 @@ -module Vagrant - module Action - module VM - class ForwardPorts - def initialize(app,env) - @app = app - end - - #-------------------------------------------------------------- - # Execution - #-------------------------------------------------------------- - def call(env) - @env = env - - # Get the ports we're forwarding - ports = forward_port_definitions - - # Warn if we're port forwarding to any privileged ports... - threshold_check(ports) - - env[:ui].info I18n.t("vagrant.actions.vm.forward_ports.forwarding") - forward_ports(ports) - - @app.call(env) - end - - # This returns an array of forwarded ports with overrides properly - # squashed. - def forward_port_definitions - # Get all the port mappings in the order they're defined and - # organize them by their guestport, taking the "last one wins" - # approach. - guest_port_mapping = {} - @env[:vm].config.vm.forwarded_ports.each do |options| - guest_port_mapping[options[:guestport]] = options - end - - # Return the values, since the order doesn't really matter - guest_port_mapping.values - end - - # This method checks for any forwarded ports on the host below - # 1024, which causes the forwarded ports to fail. - def threshold_check(ports) - ports.each do |options| - if options[:hostport] <= 1024 - @env[:ui].warn I18n.t("vagrant.actions.vm.forward_ports.privileged_ports") - return - end - end - end - - def forward_ports(mappings) - ports = [] - - interfaces = @env[:vm].driver.read_network_interfaces - - mappings.each do |options| - message_attributes = { - :guest_port => options[:guestport], - :host_port => options[:hostport], - :adapter => options[:adapter] - } - - # Assuming the only reason to establish port forwarding is - # because the VM is using Virtualbox NAT networking. Host-only - # bridged networking don't require port-forwarding and establishing - # forwarded ports on these attachment types has uncertain behaviour. - @env[:ui].info(I18n.t("vagrant.actions.vm.forward_ports.forwarding_entry", - message_attributes)) - - # Port forwarding requires the network interface to be a NAT interface, - # so verify that that is the case. - if interfaces[options[:adapter]][:type] != :nat - @env[:ui].info(I18n.t("vagrant.actions.vm.forward_ports.non_nat", - message_attributes)) - next - end - - # Add the options to the ports array to send to the driver later - ports << options.merge(:name => options[:name], :adapter => options[:adapter]) - end - - if !ports.empty? - # We only need to forward ports if there are any to forward - @env[:vm].driver.forward_ports(ports) - end - end - end - end - end -end diff --git a/lib/vagrant/action/vm/halt.rb b/lib/vagrant/action/vm/halt.rb deleted file mode 100644 index 65bc06d0d..000000000 --- a/lib/vagrant/action/vm/halt.rb +++ /dev/null @@ -1,36 +0,0 @@ -module Vagrant - module Action - module VM - class Halt - def initialize(app, env, options=nil) - @app = app - env.merge!(options || {}) - end - - def call(env) - current_state = env[:vm].state - if current_state == :running || current_state == :gurumeditation - # If the VM is running and we're not forcing, we can - # attempt a graceful shutdown - if current_state == :running && !env["force"] - env[:ui].info I18n.t("vagrant.actions.vm.halt.graceful") - env[:vm].guest.halt - end - - # If we're not powered off now, then force it - if env[:vm].state != :poweroff - env[:ui].info I18n.t("vagrant.actions.vm.halt.force") - env[:vm].driver.halt - end - - # Sleep for a second to verify that the VM properly - # cleans itself up - sleep 1 if !env["vagrant.test"] - end - - @app.call(env) - end - end - end - end -end diff --git a/lib/vagrant/action/vm/host_name.rb b/lib/vagrant/action/vm/host_name.rb deleted file mode 100644 index 8df7a9fee..000000000 --- a/lib/vagrant/action/vm/host_name.rb +++ /dev/null @@ -1,21 +0,0 @@ -module Vagrant - module Action - module VM - class HostName - def initialize(app, env) - @app = app - end - - def call(env) - @app.call(env) - - host_name = env[:vm].config.vm.host_name - if !host_name.nil? - env[:ui].info I18n.t("vagrant.actions.vm.host_name.setting") - env[:vm].guest.change_host_name(host_name) - end - end - end - end - end -end diff --git a/lib/vagrant/action/vm/import.rb b/lib/vagrant/action/vm/import.rb deleted file mode 100644 index 6e690d24d..000000000 --- a/lib/vagrant/action/vm/import.rb +++ /dev/null @@ -1,53 +0,0 @@ -module Vagrant - module Action - module VM - class Import - # The name for easy reference - def self.name - :import - end - - def initialize(app, env) - @app = app - end - - def call(env) - env[:ui].info I18n.t("vagrant.actions.vm.import.importing", :name => env[:vm].box.name) - - # Import the virtual machine - ovf_file = env[:vm].box.directory.join("box.ovf").to_s - env[:vm].uuid = env[:vm].driver.import(ovf_file) do |progress| - env[:ui].clear_line - env[:ui].report_progress(progress, 100, false) - end - - # Clear the line one last time since the progress meter doesn't disappear - # immediately. - env[:ui].clear_line - - # If we got interrupted, then the import could have been - # interrupted and its not a big deal. Just return out. - return if env[:interrupted] - - # Flag as erroneous and return if import failed - raise Errors::VMImportFailure if !env[:vm].uuid - - # Import completed successfully. Continue the chain - @app.call(env) - end - - def recover(env) - if env[:vm].created? - return if env["vagrant.error"].is_a?(Errors::VagrantError) - - # Interrupted, destroy the VM. We note that we don't want to - # validate the configuration here. - destroy_env = env.clone - destroy_env[:validate] = false - env[:action_runner].run(:destroy, destroy_env) - end - end - end - end - end -end diff --git a/lib/vagrant/action/vm/match_mac_address.rb b/lib/vagrant/action/vm/match_mac_address.rb deleted file mode 100644 index 70da6b2a4..000000000 --- a/lib/vagrant/action/vm/match_mac_address.rb +++ /dev/null @@ -1,21 +0,0 @@ -module Vagrant - module Action - module VM - class MatchMACAddress - def initialize(app, env) - @app = app - end - - def call(env) - raise Errors::VMBaseMacNotSpecified if !env[:vm].config.vm.base_mac - - # Create the proc which we want to use to modify the virtual machine - env[:ui].info I18n.t("vagrant.actions.vm.match_mac.matching") - env[:vm].driver.set_mac_address(env[:vm].config.vm.base_mac) - - @app.call(env) - end - end - end - end -end diff --git a/lib/vagrant/action/vm/network.rb b/lib/vagrant/action/vm/network.rb deleted file mode 100644 index f10d5d957..000000000 --- a/lib/vagrant/action/vm/network.rb +++ /dev/null @@ -1,406 +0,0 @@ -require 'set' - -require 'log4r' - -require 'vagrant/util/network_ip' - -module Vagrant - module Action - module VM - # This action handles all `config.vm.network` configurations by - # setting up the VM properly and enabling the networks afterword. - class Network - # Utilities to deal with network addresses - include Util::NetworkIP - - def initialize(app, env) - @logger = Log4r::Logger.new("vagrant::action::vm::network") - - @app = app - end - - def call(env) - @env = env - - # First we have to get the array of adapters that we need - # to create on the virtual machine itself, as well as the - # driver-agnostic network configurations for each. - @logger.debug("Determining adapters and networks...") - adapters = [] - networks = [] - env[:vm].config.vm.networks.each do |type, args| - # Get the normalized configuration we'll use around - config = send("#{type}_config", args) - - # Get the virtualbox adapter configuration - adapter = send("#{type}_adapter", config) - adapters << adapter - - # Get the network configuration - network = send("#{type}_network_config", config) - network[:_auto_config] = true if config[:auto_config] - networks << network - end - - if !adapters.empty? - # Automatically assign an adapter number to any adapters - # that aren't explicitly set. - @logger.debug("Assigning adapter locations...") - assign_adapter_locations(adapters) - - # Verify that our adapters are good just prior to enabling them. - verify_adapters(adapters) - - # Create all the network interfaces - @logger.info("Enabling adapters...") - env[:ui].info I18n.t("vagrant.actions.vm.network.preparing") - env[:vm].driver.enable_adapters(adapters) - end - - # Continue the middleware chain. We're done with our VM - # setup until after it is booted. - @app.call(env) - - if !adapters.empty? && !networks.empty? - # Determine the interface numbers for the guest. - assign_interface_numbers(networks, adapters) - - # Configure all the network interfaces on the guest. We only - # want to configure the networks that have `auto_config` setup. - networks_to_configure = networks.select { |n| n[:_auto_config] } - env[:ui].info I18n.t("vagrant.actions.vm.network.configuring") - env[:vm].guest.configure_networks(networks_to_configure) - end - end - - # This method assigns the adapter to use for the adapter. - # e.g. it says that the first adapter is actually on the - # virtual machine's 2nd adapter location. - # - # It determines the adapter numbers by simply finding the - # "next available" in each case. - # - # The adapters are modified in place by adding an ":adapter" - # field to each. - def assign_adapter_locations(adapters) - available = Set.new(1..8) - - # Determine which NICs are actually available. - interfaces = @env[:vm].driver.read_network_interfaces - interfaces.each do |number, nic| - # Remove the number from the available NICs if the - # NIC is in use. - available.delete(number) if nic[:type] != :none - end - - # Based on the available set, assign in order to - # the adapters. - available = available.to_a.sort - @logger.debug("Available NICs: #{available.inspect}") - adapters.each do |adapter| - # Ignore the adapters that already have been assigned - if !adapter[:adapter] - # If we have no available adapters, then that is an exceptional - # event. - raise Errors::NetworkNoAdapters if available.empty? - - # Otherwise, assign as the adapter the next available item - adapter[:adapter] = available.shift - end - end - end - - # Verifies that the adapter configurations look good. This will - # raise an exception in the case that any errors occur. - def verify_adapters(adapters) - # Verify that there are no collisions in the adapters being used. - used = Set.new - adapters.each do |adapter| - raise Errors::NetworkAdapterCollision if used.include?(adapter[:adapter]) - used.add(adapter[:adapter]) - end - end - - # Assigns the actual interface number of a network based on the - # enabled NICs on the virtual machine. - # - # This interface number is used by the guest to configure the - # NIC on the guest VM. - # - # The networks are modified in place by adding an ":interface" - # field to each. - def assign_interface_numbers(networks, adapters) - current = 0 - adapter_to_interface = {} - - # Make a first pass to assign interface numbers by adapter location - vm_adapters = @env[:vm].driver.read_network_interfaces - vm_adapters.sort.each do |number, adapter| - if adapter[:type] != :none - # Not used, so assign the interface number and increment - adapter_to_interface[number] = current - current += 1 - end - end - - # Make a pass through the adapters to assign the :interface - # key to each network configuration. - adapters.each_index do |i| - adapter = adapters[i] - network = networks[i] - - # Figure out the interface number by simple lookup - network[:interface] = adapter_to_interface[adapter[:adapter]] - end - end - - def hostonly_config(args) - ip = args[0] - options = args[1] || {} - - # Determine if we're dealing with a static IP or a DHCP-served IP. - type = ip == :dhcp ? :dhcp : :static - - # Default IP is in the 20-bit private network block for DHCP based networks - ip = "172.28.128.1" if type == :dhcp - - options = { - :type => type, - :ip => ip, - :netmask => "255.255.255.0", - :adapter => nil, - :mac => nil, - :name => nil, - :auto_config => true - }.merge(options) - - # Verify that this hostonly network wouldn't conflict with any - # bridged interfaces - verify_no_bridge_collision(options) - - # Get the network address and IP parts which are used for many - # default calculations - netaddr = network_address(options[:ip], options[:netmask]) - ip_parts = netaddr.split(".").map { |i| i.to_i } - - # Calculate the adapter IP, which we assume is the IP ".1" at the - # end usually. - adapter_ip = ip_parts.dup - adapter_ip[3] += 1 - options[:adapter_ip] ||= adapter_ip.join(".") - - if type == :dhcp - # Calculate the DHCP server IP, which is the network address - # with the final octet + 2. So "172.28.0.0" turns into "172.28.0.2" - dhcp_ip = ip_parts.dup - dhcp_ip[3] += 2 - options[:dhcp_ip] ||= dhcp_ip.join(".") - - # Calculate the lower and upper bound for the DHCP server - dhcp_lower = ip_parts.dup - dhcp_lower[3] += 3 - options[:dhcp_lower] ||= dhcp_lower.join(".") - - dhcp_upper = ip_parts.dup - dhcp_upper[3] = 254 - options[:dhcp_upper] ||= dhcp_upper.join(".") - end - - # Return the hostonly network configuration - return options - end - - def hostonly_adapter(config) - @logger.debug("Searching for matching network: #{config[:ip]}") - interface = find_matching_hostonly_network(config) - - if !interface - @logger.debug("Network not found. Creating if we can.") - - # It is an error case if a specific name was given but the network - # doesn't exist. - if config[:name] - raise Errors::NetworkNotFound, :name => config[:name] - end - - # Otherwise, we create a new network and put the net network - # in the list of available networks so other network definitions - # can use it! - interface = create_hostonly_network(config) - @logger.debug("Created network: #{interface[:name]}") - end - - if config[:type] == :dhcp - # Check that if there is a DHCP server attached on our interface, - # then it is identical. Otherwise, we can't set it. - if interface[:dhcp] - valid = interface[:dhcp][:ip] == config[:dhcp_ip] && - interface[:dhcp][:lower] == config[:dhcp_lower] && - interface[:dhcp][:upper] == config[:dhcp_upper] - - raise Errors::NetworkDHCPAlreadyAttached if !valid - - @logger.debug("DHCP server already properly configured") - else - # Configure the DHCP server for the network. - @logger.debug("Creating a DHCP server...") - @env[:vm].driver.create_dhcp_server(interface[:name], config) - end - end - - return { - :adapter => config[:adapter], - :type => :hostonly, - :hostonly => interface[:name], - :mac_address => config[:mac], - :nic_type => config[:nic_type] - } - end - - def hostonly_network_config(config) - return { - :type => config[:type], - :adapter_ip => config[:adapter_ip], - :ip => config[:ip], - :netmask => config[:netmask] - } - end - - # Creates a new hostonly network that matches the network requested - # by the given host-only network configuration. - def create_hostonly_network(config) - # Create the options that are going to be used to create our - # new network. - options = config.dup - options[:ip] = options[:adapter_ip] - - @env[:vm].driver.create_host_only_network(options) - end - - # Finds a host only network that matches our configuration on VirtualBox. - # This will return nil if a matching network does not exist. - def find_matching_hostonly_network(config) - this_netaddr = network_address(config[:ip], config[:netmask]) - - @env[:vm].driver.read_host_only_interfaces.each do |interface| - if config[:name] && config[:name] == interface[:name] - return interface - elsif this_netaddr == network_address(interface[:ip], interface[:netmask]) - return interface - end - end - - nil - end - - # Verifies that a host-only network subnet would not collide with - # a bridged networking interface. - # - # If the subnets overlap in any way then the host only network - # will not work because the routing tables will force the traffic - # onto the real interface rather than the virtualbox interface. - def verify_no_bridge_collision(options) - this_netaddr = network_address(options[:ip], options[:netmask]) - - @env[:vm].driver.read_bridged_interfaces.each do |interface| - that_netaddr = network_address(interface[:ip], interface[:netmask]) - raise Errors::NetworkCollision if this_netaddr == that_netaddr && interface[:status] != "Down" - end - end - - def bridged_config(args) - options = args[0] || {} - options = {} if !options.is_a?(Hash) - - return { - :adapter => nil, - :mac => nil, - :bridge => nil, - :auto_config => true, - :use_dhcp_assigned_default_route => false - }.merge(options) - end - - def bridged_adapter(config) - # Find the bridged interfaces that are available - bridgedifs = @env[:vm].driver.read_bridged_interfaces - bridgedifs.delete_if { |interface| interface[:status] == "Down" } - - # The name of the chosen bridge interface will be assigned to this - # variable. - chosen_bridge = nil - - if config[:bridge] - @logger.debug("Bridge was directly specified in config, searching for: #{config[:bridge]}") - - # Search for a matching bridged interface - bridgedifs.each do |interface| - if interface[:name].downcase == config[:bridge].downcase - @logger.debug("Specific bridge found as configured in the Vagrantfile. Using it.") - chosen_bridge = interface[:name] - break - end - end - - # If one wasn't found, then we notify the user here. - if !chosen_bridge - @env[:ui].info I18n.t("vagrant.actions.vm.bridged_networking.specific_not_found", - :bridge => config[:bridge]) - end - end - - # If we still don't have a bridge chosen (this means that one wasn't - # specified in the Vagrantfile, or the bridge specified in the Vagrantfile - # wasn't found), then we fall back to the normal means of searchign for a - # bridged network. - if !chosen_bridge - if bridgedifs.length == 1 - # One bridgable interface? Just use it. - chosen_bridge = bridgedifs[0][:name] - @logger.debug("Only one bridged interface available. Using it by default.") - else - # More than one bridgable interface requires a user decision, so - # show options to choose from. - @env[:ui].info I18n.t("vagrant.actions.vm.bridged_networking.available", - :prefix => false) - bridgedifs.each_index do |index| - interface = bridgedifs[index] - @env[:ui].info("#{index + 1}) #{interface[:name]}", :prefix => false) - end - - # The range of valid choices - valid = Range.new(1, bridgedifs.length) - - # The choice that the user has chosen as the bridging interface - choice = nil - while !valid.include?(choice) - choice = @env[:ui].ask("What interface should the network bridge to? ") - choice = choice.to_i - end - - chosen_bridge = bridgedifs[choice - 1][:name] - end - end - - @logger.info("Bridging adapter #{config[:adapter]} to #{chosen_bridge}") - - # Given the choice we can now define the adapter we're using - return { - :adapter => config[:adapter], - :type => :bridged, - :bridge => chosen_bridge, - :mac_address => config[:mac], - :nic_type => config[:nic_type] - } - end - - def bridged_network_config(config) - return { - :type => :dhcp, - :use_dhcp_assigned_default_route => config[:use_dhcp_assigned_default_route] - } - end - end - end - end -end diff --git a/lib/vagrant/action/vm/nfs.rb b/lib/vagrant/action/vm/nfs.rb deleted file mode 100644 index 8aa81d31b..000000000 --- a/lib/vagrant/action/vm/nfs.rb +++ /dev/null @@ -1,196 +0,0 @@ -require 'digest/md5' -require 'fileutils' -require 'pathname' - -require 'log4r' - -module Vagrant - module Action - module VM - # Enables NFS based shared folders. `nfsd` must already be installed - # on the host machine, and NFS client must already be installed on - # the guest machine. - # - # This is a two part process: - # - # 1. Adds an entry to `/etc/exports` on the host machine using - # the host class to export the proper folder to the proper - # machine. - # 2. After boot, runs `mount` on the guest to mount the shared - # folder. - # - class NFS - def initialize(app,env) - @logger = Log4r::Logger.new("vagrant::action::vm::nfs") - @app = app - @env = env - - verify_settings if nfs_enabled? - end - - def call(env) - @env = env - - extract_folders - - if !folders.empty? - prepare_folders - export_folders - end - - @app.call(env) - - mount_folders if !folders.empty? - end - - # Returns the folders which are to be synced via NFS. - def folders - @folders ||= {} - end - - # Removes the NFS enabled shared folders from the configuration, - # so they will no longer be mounted by the actual shared folder - # task. - def extract_folders - # Load the NFS enabled shared folders - @folders = {} - @env[:vm].config.vm.shared_folders.each do |key, opts| - if opts[:nfs] - # Duplicate the options, set the hostpath, and set disabled on the original - # options so the ShareFolders middleware doesn't try to mount it. - folder = opts.dup - hostpath = Pathname.new(opts[:hostpath]).expand_path(@env[:root_path]) - - if !hostpath.directory? && opts[:create] - # Host path doesn't exist, so let's create it. - @logger.debug("Host path doesn't exist, creating: #{hostpath}") - - begin - FileUtils.mkpath(hostpath) - rescue Errno::EACCES - raise Errors::SharedFolderCreateFailed, :path => hostpath.to_s - end - end - - # Set the hostpath now that it exists. - folder[:hostpath] = hostpath.to_s - - # Assign the folder to our instance variable for later use - @folders[key] = folder - - # Disable the folder so that regular shared folders don't try to - # mount it. - opts[:disabled] = true - end - end - end - - # Prepares the settings for the NFS folders, such as setting the - # options on the NFS folders. - def prepare_folders - @folders = @folders.inject({}) do |acc, data| - key, opts = data - opts[:map_uid] = prepare_permission(:uid, opts) - opts[:map_gid] = prepare_permission(:gid, opts) - opts[:nfs_version] ||= 3 - - # The poor man's UUID. An MD5 hash here is sufficient since - # we need a 32 character "uuid" to represent the filesystem - # of an export. Hashing the host path is safe because two of - # the same host path will hash to the same fsid. - opts[:uuid] = Digest::MD5.hexdigest(opts[:hostpath]) - - acc[key] = opts - acc - end - end - - # Prepares the UID/GID settings for a single folder. - def prepare_permission(perm, opts) - key = "map_#{perm}".to_sym - return nil if opts.has_key?(key) && opts[key].nil? - - # The options on the hash get priority, then the default - # values - value = opts.has_key?(key) ? opts[key] : @env[:vm].config.nfs.send(key) - return value if value != :auto - - # Get UID/GID from folder if we've made it this far - # (value == :auto) - stat = File.stat(opts[:hostpath]) - return stat.send(perm) - end - - # Uses the host class to export the folders via NFS. This typically - # involves adding a line to `/etc/exports` for this VM, but it is - # up to the host class to define the specific behavior. - def export_folders - @env[:ui].info I18n.t("vagrant.actions.vm.nfs.exporting") - @env[:host].nfs_export(@env[:vm].uuid, guest_ip, folders) - end - - # Uses the system class to mount the NFS folders. - def mount_folders - @env[:ui].info I18n.t("vagrant.actions.vm.nfs.mounting") - - # Only mount the folders which have a guest path specified - mount_folders = {} - folders.each do |name, opts| - if opts[:guestpath] - mount_folders[name] = opts.dup - end - end - - @env[:vm].guest.mount_nfs(host_ip, mount_folders) - end - - # Returns the IP address of the first host only network adapter - # - # @return [String] - def host_ip - @env[:vm].driver.read_network_interfaces.each do |adapter, opts| - if opts[:type] == :hostonly - @env[:vm].driver.read_host_only_interfaces.each do |interface| - if interface[:name] == opts[:hostonly] - return interface[:ip] - end - end - end - end - - nil - end - - # Returns the IP address of the guest by looking at the first - # enabled host only network. - # - # @return [String] - def guest_ip - @env[:vm].config.vm.networks.each do |type, args| - if type == :hostonly && args[0].is_a?(String) - return args[0] - end - end - - nil - end - - # Checks if there are any NFS enabled shared folders. - def nfs_enabled? - @env[:vm].config.vm.shared_folders.each do |key, opts| - return true if opts[:nfs] - end - - false - end - - # Verifies that the host is set and supports NFS. - def verify_settings - raise Errors::NFSHostRequired if @env[:host].nil? - raise Errors::NFSNotSupported if !@env[:host].nfs? - raise Errors::NFSNoHostNetwork if !guest_ip - end - end - end - end -end diff --git a/lib/vagrant/action/vm/provision.rb b/lib/vagrant/action/vm/provision.rb deleted file mode 100644 index 56be8a8e6..000000000 --- a/lib/vagrant/action/vm/provision.rb +++ /dev/null @@ -1,61 +0,0 @@ -require "log4r" - -module Vagrant - module Action - module VM - class Provision - def initialize(app, env) - @logger = Log4r::Logger.new("vagrant::action::vm::provision") - @app = app - - env["provision.enabled"] = true if !env.has_key?("provision.enabled") - end - - def call(env) - @env = env - - provisioners = nil - - # We set this here so that even if this value is changed in the future, - # it stays constant to what we expect here in this moment. - enabled = env["provision.enabled"] - # Instantiate and prepare the provisioners. Preparation must happen here - # so that shared folders and such can properly take effect. - provisioners = enabled_provisioners - provisioners.map { |p| p.prepare } - - @app.call(env) - - if enabled - # Take prepared provisioners and run the provisioning - provisioners.each do |instance| - @env[:ui].info I18n.t("vagrant.actions.vm.provision.beginning", - :provisioner => instance.class) - instance.provision! - end - end - end - - def enabled_provisioners - enabled = [] - @env[:vm].config.vm.provisioners.each do |provisioner| - if @env["provision.types"] - # If we've specified types of provisioners to enable, then we - # only use those provisioners, and skip any that we haven't - # specified. - if !@env["provision.types"].include?(provisioner.shortcut.to_s) - @logger.debug("Skipping provisioner: #{provisioner.shortcut}") - next - end - end - - enabled << provisioner.provisioner.new(@env, provisioner.config) - end - - # Return the enable provisioners - enabled - end - end - end - end -end diff --git a/lib/vagrant/action/vm/provisioner_cleanup.rb b/lib/vagrant/action/vm/provisioner_cleanup.rb deleted file mode 100644 index 1c5b2f0e6..000000000 --- a/lib/vagrant/action/vm/provisioner_cleanup.rb +++ /dev/null @@ -1,26 +0,0 @@ -module Vagrant - module Action - module VM - class ProvisionerCleanup - def initialize(app, env) - @app = app - @env = env - end - - def call(env) - enabled_provisioners.each do |instance| - instance.cleanup - end - - @app.call(env) - end - - def enabled_provisioners - @env[:vm].config.vm.provisioners.map do |provisioner| - provisioner.provisioner.new(@env, provisioner.config) - end - end - end - end - end -end diff --git a/lib/vagrant/action/vm/prune_nfs_exports.rb b/lib/vagrant/action/vm/prune_nfs_exports.rb deleted file mode 100644 index b8b3b3061..000000000 --- a/lib/vagrant/action/vm/prune_nfs_exports.rb +++ /dev/null @@ -1,20 +0,0 @@ -module Vagrant - module Action - module VM - class PruneNFSExports - def initialize(app, env) - @app = app - end - - def call(env) - if env[:host] - valid_ids = env[:vm].driver.read_vms - env[:host].nfs_prune(valid_ids) - end - - @app.call(env) - end - end - end - end -end diff --git a/lib/vagrant/action/vm/sane_defaults.rb b/lib/vagrant/action/vm/sane_defaults.rb deleted file mode 100644 index f2dd31ab9..000000000 --- a/lib/vagrant/action/vm/sane_defaults.rb +++ /dev/null @@ -1,78 +0,0 @@ -require "log4r" - -module Vagrant - module Action - module VM - # This middleware enforces some sane defaults on the virtualbox - # VM which help with performance, stability, and in some cases - # behavior. - class SaneDefaults - def initialize(app, env) - @logger = Log4r::Logger.new("vagrant::action::vm::sanedefaults") - @app = app - end - - def call(env) - # Set the env on an instance variable so we can access it in - # helpers. - @env = env - - # Enable the host IO cache on the sata controller. Note that - # if this fails then its not a big deal, so we don't raise any - # errors. The Host IO cache vastly improves disk IO performance - # for VMs. - command = [ - "storagectl", env[:vm].uuid, - "--name", "SATA Controller", - "--hostiocache", "on" - ] - attempt_and_log(command, "Enabling the Host I/O cache on the SATA controller...") - - enable_dns_proxy = true - begin - contents = File.read("/etc/resolv.conf") - - if contents =~ /^nameserver 127\.0\.0\.1$/ - # The use of both natdnsproxy and natdnshostresolver break on - # Ubuntu 12.04 that uses resolvconf with localhost. When used - # VirtualBox will give the client dns server 10.0.2.3, while - # not binding to that address itself. Therefore disable this - # feature if host uses the resolvconf server 127.0.0.1 - @logger.info("Disabling DNS proxy since resolv.conf contains 127.0.0.1") - enable_dns_proxy = false - end - rescue Errno::ENOENT; end - - # Enable/disable the NAT DNS proxy as necessary - if enable_dns_proxy - command = [ - "modifyvm", env[:vm].uuid, - "--natdnsproxy1", "on" - ] - attempt_and_log(command, "Enable the NAT DNS proxy on adapter 1...") - else - command = [ "modifyvm", env[:vm].uuid, "--natdnsproxy1", "off" ] - attempt_and_log(command, "Disable the NAT DNS proxy on adapter 1...") - command = [ "modifyvm", env[:vm].uuid, "--natdnshostresolver1", "off" ] - attempt_and_log(command, "Disable the NAT DNS resolver on adapter 1...") - end - - @app.call(env) - end - - protected - - # This is just a helper method that executes a single command, logs - # the given string to the log, and also includes the exit status in - # the log message. - # - # @param [Array] command Command to run - # @param [String] log Log message to write. - def attempt_and_log(command, log) - result = @env[:vm].driver.execute_command(command) - @logger.info("#{log} (exit status = #{result.exit_code})") - end - end - end - end -end diff --git a/lib/vagrant/action/vm/setup_package_files.rb b/lib/vagrant/action/vm/setup_package_files.rb deleted file mode 100644 index f45210707..000000000 --- a/lib/vagrant/action/vm/setup_package_files.rb +++ /dev/null @@ -1,54 +0,0 @@ -require 'pathname' - -module Vagrant - module Action - module VM - # Sets up the mapping of files to copy into the package and verifies - # that the files can be properly copied. - class SetupPackageFiles - def initialize(app, env) - @app = app - - env["package.include"] ||= [] - env["package.vagrantfile"] ||= nil - end - - def call(env) - files = {} - env["package.include"].each do |file| - source = Pathname.new(file) - dest = nil - - # If the source is relative then we add the file as-is to the include - # directory. Otherwise, we copy only the file into the root of the - # include directory. Kind of strange, but seems to match what people - # expect based on history. - if source.relative? - dest = source - else - dest = source.basename - end - - # Assign the mapping - files[file] = dest - end - - if env["package.vagrantfile"] - # Vagrantfiles are treated special and mapped to a specific file - files[env["package.vagrantfile"]] = "_Vagrantfile" - end - - # Verify the mapping - files.each do |from, _| - raise Errors::PackageIncludeMissing, :file => from if !File.exist?(from) - end - - # Save the mapping - env["package.files"] = files - - @app.call(env) - end - end - end - end -end diff --git a/lib/vagrant/action/vm/share_folders.rb b/lib/vagrant/action/vm/share_folders.rb deleted file mode 100644 index 29dc4ccf8..000000000 --- a/lib/vagrant/action/vm/share_folders.rb +++ /dev/null @@ -1,114 +0,0 @@ -require 'pathname' - -require 'log4r' - -module Vagrant - module Action - module VM - class ShareFolders - def initialize(app, env) - @logger = Log4r::Logger.new("vagrant::action::vm::share_folders") - @app = app - end - - def call(env) - @env = env - - prepare_folders - create_metadata - - @app.call(env) - - mount_shared_folders - end - - # This method returns an actual list of VirtualBox shared - # folders to create and their proper path. - def shared_folders - @env[:vm].config.vm.shared_folders.inject({}) do |acc, data| - key, value = data - - next acc if value[:disabled] - - # This to prevent overwriting the actual shared folders data - value = value.dup - acc[key] = value - acc - end - end - - # Prepares the shared folders by verifying they exist and creating them - # if they don't. - def prepare_folders - shared_folders.each do |name, options| - hostpath = Pathname.new(options[:hostpath]).expand_path(@env[:root_path]) - - if !hostpath.directory? && options[:create] - # Host path doesn't exist, so let's create it. - @logger.debug("Host path doesn't exist, creating: #{hostpath}") - - begin - hostpath.mkpath - rescue Errno::EACCES - raise Errors::SharedFolderCreateFailed, :path => hostpath.to_s - end - end - end - end - - def create_metadata - @env[:ui].info I18n.t("vagrant.actions.vm.share_folders.creating") - - folders = [] - shared_folders.each do |name, data| - folders << { - :name => name, - :hostpath => File.expand_path(data[:hostpath], @env[:root_path]), - :transient => data[:transient] - } - end - - @env[:vm].driver.share_folders(folders) - end - - def mount_shared_folders - @env[:ui].info I18n.t("vagrant.actions.vm.share_folders.mounting") - - # short guestpaths first, so we don't step on ourselves - folders = shared_folders.sort_by do |name, data| - if data[:guestpath] - data[:guestpath].length - else - # A long enough path to just do this at the end. - 10000 - end - end - - # Go through each folder and mount - folders.each do |name, data| - if data[:guestpath] - # Guest path specified, so mount the folder to specified point - @env[:ui].info(I18n.t("vagrant.actions.vm.share_folders.mounting_entry", - :name => name, - :guest_path => data[:guestpath])) - - # Dup the data so we can pass it to the guest API - data = data.dup - - # Calculate the owner and group - data[:owner] ||= @env[:vm].config.ssh.username - data[:group] ||= @env[:vm].config.ssh.username - - # Mount the actual folder - @env[:vm].guest.mount_shared_folder(name, data[:guestpath], data) - else - # If no guest path is specified, then automounting is disabled - @env[:ui].info(I18n.t("vagrant.actions.vm.share_folders.nomount_entry", - :name => name)) - end - end - end - end - end - end -end