Class: Vagrant::Action::VM::Network

Inherits:
Object
  • Object
show all
Defined in:
lib/vagrant/action/vm/network.rb

Overview

Networking middleware for Vagrant. This enables host only networking on VMs if configured as such.

Instance Method Summary collapse

Constructor Details

#initialize(app, env) ⇒ Network

Returns a new instance of Network.



7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/vagrant/action/vm/network.rb', line 7

def initialize(app, env)
  @app = app
  @env = env

  if enable_network? && Util::Platform.windows? && Util::Platform.bit64?
    raise Errors::NetworkNotImplemented
  end

  env["config"].vm.network_options.compact.each do |network_options|
    raise Errors::NetworkCollision if !verify_no_bridge_collision(network_options)
  end
end

Instance Method Details

#apply_netmask(ip, netmask) ⇒ Object

Applies a netmask to an IP and returns the corresponding parts.



113
114
115
116
117
118
119
120
# File 'lib/vagrant/action/vm/network.rb', line 113

def apply_netmask(ip, netmask)
  ip = split_ip(ip)
  netmask = split_ip(netmask)

  ip.map do |part|
    part & netmask.shift
  end
end

#assign_networkObject

Enables and assigns the host only network to the proper adapter on the VM, and saves the adapter.



60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/vagrant/action/vm/network.rb', line 60

def assign_network
  @env.ui.info I18n.t("vagrant.actions.vm.network.preparing")

  @env.env.config.vm.network_options.compact.each do |network_options|
    adapter = @env["vm"].vm.network_adapters[network_options[:adapter]]
    adapter.enabled = true
    adapter.attachment_type = :host_only
    adapter.host_interface = network_name(network_options)
    adapter.mac_address = network_options[:mac].gsub(':', '') if network_options[:mac]
    adapter.save
  end
end

#call(env) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/vagrant/action/vm/network.rb', line 20

def call(env)
  @env = env
  assign_network if enable_network?

  @app.call(env)

  if enable_network?
    @env.ui.info I18n.t("vagrant.actions.vm.network.enabling")
    @env.env.config.vm.network_options.compact.each do |network_options|
      @env["vm"].system.prepare_host_only_network(network_options)
      @env["vm"].system.enable_host_only_network(network_options)
    end
  end
end

#enable_network?Boolean

Returns:

  • (Boolean)


54
55
56
# File 'lib/vagrant/action/vm/network.rb', line 54

def enable_network?
  !@env.env.config.vm.network_options.compact.empty?
end

#matching_network?(interface, net_options) ⇒ Boolean

Tests if a network matches the given options by applying the netmask to the IP of the network and also to the IP of the virtual machine and see if they match.

Returns:

  • (Boolean)


105
106
107
108
109
# File 'lib/vagrant/action/vm/network.rb', line 105

def matching_network?(interface, net_options)
  interface.network_mask == net_options[:netmask] &&
    apply_netmask(interface.ip_address, interface.network_mask) ==
    apply_netmask(net_options[:ip], net_options[:netmask])
end

#network_ip(ip, netmask) ⇒ Object

Returns a "network IP" which is a "good choice" for the IP for the actual network based on the netmask.



131
132
133
134
135
# File 'lib/vagrant/action/vm/network.rb', line 131

def network_ip(ip, netmask)
  parts = apply_netmask(ip, netmask)
  parts[3] += 1;
  parts.join(".")
end

#network_name(net_options) ⇒ Object

Returns the name of the proper host only network, or creates it if it does not exist. Vagrant determines if the host only network exists by comparing the netmask and the IP.



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/vagrant/action/vm/network.rb', line 76

def network_name(net_options)
  # First try to find a matching network
  interfaces = VirtualBox::Global.global.host.network_interfaces
  interfaces.each do |ni|
    # Ignore non-host only interfaces which may also match,
    # since they're not valid options.
    next if ni.interface_type != :host_only

    if net_options[:name]
      return ni.name if net_options[:name] == ni.name
    else
      return ni.name if matching_network?(ni, net_options)
    end
  end

  raise Errors::NetworkNotFound, :name => net_options[:name] if net_options[:name]

  # One doesn't exist, create it.
  @env.ui.info I18n.t("vagrant.actions.vm.network.creating")

  ni = interfaces.create
  ni.enable_static(network_ip(net_options[:ip], net_options[:netmask]),
                   net_options[:netmask])
  ni.name
end

#split_ip(ip) ⇒ Object

Splits an IP and converts each portion into an int.



123
124
125
126
127
# File 'lib/vagrant/action/vm/network.rb', line 123

def split_ip(ip)
  ip.split(".").map do |i|
    i.to_i
  end
end

#verify_no_bridge_collision(net_options) ⇒ Object

Verifies that there is no collision with a bridged network interface for the given network options.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/vagrant/action/vm/network.rb', line 37

def verify_no_bridge_collision(net_options)
  interfaces = VirtualBox::Global.global.host.network_interfaces
  interfaces.each do |ni|
    next if ni.interface_type == :host_only

    result = if net_options[:name]
      true if net_options[:name] == ni.name
    else
      true if matching_network?(ni, net_options)
    end

    return false if result
  end

  true
end