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.



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

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.



67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/vagrant/action/vm/network.rb', line 67

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_only_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
34
35
36
37
38
39
40
# 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")

    # Prepare for new networks...
    options = @env.env.config.vm.network_options.compact
    options.each do |network_options|
      @env["vm"].system.prepare_host_only_network(network_options)
    end

    # Then enable the networks...
    options.each do |network_options|
      @env["vm"].system.enable_host_only_network(network_options)
    end
  end
end

#enable_network?Boolean

Returns:

  • (Boolean)


61
62
63
# File 'lib/vagrant/action/vm/network.rb', line 61

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)


112
113
114
115
116
# File 'lib/vagrant/action/vm/network.rb', line 112

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.



138
139
140
141
142
# File 'lib/vagrant/action/vm/network.rb', line 138

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.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/vagrant/action/vm/network.rb', line 83

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.



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

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.



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/vagrant/action/vm/network.rb', line 44

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