add libvirt interface tcp tunnel support.

Useful when configuring Virtualized Switch topologies using Switch VMs like Cumulus
Linux.

vagrant network interface auto_config is disabled in the code. This may be
re-enabled in a future update, once it is better understood how to
auto configure these types of links. All guestOS ports, for now, that are
connected to a tcp tunnel are in a link down state.

TCP tunnels allow guest OSes to exchange STP and LLDP information as
if they are directly connected to each other.

This is not possible with the default virtual switch network mode.

Reference:
https://libvirt.org/formatdomain.html#elementsNICSTCP
This commit is contained in:
stanley karunditu 2015-07-11 10:49:00 -04:00
parent ab34b7d29b
commit 789fa369c8
6 changed files with 66 additions and 5 deletions

View File

@ -213,7 +213,11 @@ Vagrant.configure("2") do |config|
## Networks
Networking features in the form of `config.vm.network` support private networks
concept.
concept. It supports both the virtual network switch routing types and the point to
point Guest OS to Guest OS setting using TCP tunnel interfaces.
http://wiki.libvirt.org/page/VirtualNetworking
https://libvirt.org/formatdomain.html#elementsNICSTCP
Public Network interfaces are currently implemented using the macvtap driver. The macvtap
driver is only available with the Linux Kernel version >= 2.6.24. See the following libvirt
@ -221,14 +225,33 @@ documentation for the details of the macvtap usage.
http://www.libvirt.org/formatdomain.html#elementsNICSDirect
An examples of network interface definitions:
```ruby
# Private network
# Private network using virtual network switching
config.vm.define :test_vm1 do |test_vm1|
test_vm1.vm.network :private_network, :ip => "10.20.30.40"
end
# Private network. Point to Point between 2 Guest OS using a TCP tunnel
# Guest 1
config.vm.define :test_vm1 do |test_vm1|
test_vm1.vm.network :private_network,
:libvirt__tcp_tunnel_type => 'server',
# default is 127.0.0.1 if omitted
# :libvirt__tcp_tunnel_ip => '127.0.0.1',
:libvirt__tcp_tunnel_port => '11111'
# Guest 2
config.vm.define :test_vm1 do |test_vm1|
test_vm1.vm.network :private_network,
:libvirt__tcp_tunnel_type => 'client',
# default is 127.0.0.1 if omitted
# :libvirt__tcp_tunnel_ip => '127.0.0.1',
:libvirt__tcp_tunnel_port => '11111'
# Public Network
config.vm.define :test_vm1 do |test_vm1|
test_vm1.vm.network :public_network,
@ -290,9 +313,19 @@ starts with 'libvirt__' string. Here is a list of those options:
* `:libvirt__forward_device` - Name of interface/device, where network should
be forwarded (NATed or routed). Used only when creating new network. By
default, all physical interfaces are used.
* `:libvirt_tcp_tunnel_type` - Set it to "server" or "client" to enable TCP
tunnel interface configuration. This configuration type uses TCP tunnels to
generate point to point connections between Guests. Useful for Switch VMs like
Cumulus Linux. No virtual switch setting like "libvirt__network_name" applies with TCP
tunnel interfaces and will be ignored if configured.
* `:libvirt_tcp_tunnel_ip` - Sets the source IP of the TCP Tunnel interface. By
default this is `127.0.0.1`
* `:libvirt_tcp_tunnel_port` - Sets the TCP Tunnel interface port that either
the client will connect to, or the server will listen on.
* `:mac` - MAC address for the interface.
* `:model_type` - parameter specifies the model of the network adapter when you create a domain value by default virtio KVM believe possible values, see the documentation for libvirt
When the option `:libvirt__dhcp_enabled` is to to 'false' it shouldn't matter
whether the virtual network contains a DHCP server or not and vagrant-libvirt
should not fail on it. The only situation where vagrant-libvirt should fail

View File

@ -36,7 +36,6 @@ module VagrantPlugins
adapters = []
# Vagrant gives you adapter 0 by default
# Assign interfaces to slots.
configured_networks(env, @logger).each do |options|
@ -70,7 +69,6 @@ module VagrantPlugins
@mac = iface_configuration.fetch(:mac, false)
@model_type = iface_configuration.fetch(:model_type, @nic_model_type)
template_name = 'interface'
# Configuration for public interfaces which use the macvtap driver
if iface_configuration[:iface_type] == :public_network
@device = iface_configuration.fetch(:dev, 'eth0')
@ -80,8 +78,18 @@ module VagrantPlugins
template_name = 'public_interface'
@logger.info("Setting up public interface using device #{@device} in mode #{@mode}")
@ovs = iface_configuration.fetch(:ovs, false)
# configuration for tcp tunnel interfaces (p2p conn btwn guest OSes)
elsif iface_configuration.fetch(:tcp_tunnel_type, nil)
@tcp_tunnel_port = iface_configuration.fetch(:tcp_tunnel_port, nil)
raise Errors::TcpTunnelPortNotDefined if @tcp_tunnel_port.nil?
@tcp_tunnel_ip = iface_configuration.fetch(:tcp_tunnel_address, '127.0.0.1')
@type = iface_configuration.fetch(:tcp_tunnel_type)
@model_type = iface_configuration.fetch(:model_type, @nic_model_type)
template_name = 'tcp_tunnel_interface'
@logger.info("Setting up #{@type} tunnel interface using #{@tcp_tunnel_ip} port #{@tcp_tunnel_port}")
end
message = "Creating network interface eth#{@iface_number}"
message << " connected to network #{@network_name}."
if @mac
@ -144,6 +152,9 @@ module VagrantPlugins
network[:type] = :dhcp
end
# do not run configure_networks for tcp tunnel interfaces
next if options.fetch(:tcp_tunnel_type, nil)
networks_to_configure << network
end
@ -163,6 +174,9 @@ module VagrantPlugins
# Return network name according to interface options.
def interface_network(libvirt_client, options)
# no need to get interface network for tcp tunnel config
return 'tcp_tunnel' if options.fetch(:tcp_tunnel_type, nil)
if options[:network_name]
@logger.debug "Found network by name"
return options[:network_name]

View File

@ -35,7 +35,8 @@ module VagrantPlugins
# available, create it if possible. Otherwise raise an error.
configured_networks(env, @logger).each do |options|
# Only need to create private networks
next if options[:iface_type] != :private_network
next if options[:iface_type] != :private_network or
options.fetch(:tcp_tunnel_type, nil)
@logger.debug "Searching for network with options #{options}"
# should fix other methods so this doesn't have to be instance var

View File

@ -106,6 +106,10 @@ module VagrantPlugins
error_key(:activate_network_error)
end
class TcpTunnelPortNotDefined < VagrantLibvirtError
error_key(:tcp_tunnel_port_not_defined)
end
# Other exceptions
class InterfaceSlotNotAvailable < VagrantLibvirtError
error_key(:interface_slot_not_available)

View File

@ -0,0 +1,7 @@
<interface type='<%= @type %>'>
<% if @mac %>
<mac address='<%= @mac %>'/>
<% end %>
<source address='<%=@tcp_tunnel_ip%>' port='<%= @tcp_tunnel_port %>'/>
<model type='<%=@model_type%>'/>
</interface>

View File

@ -135,6 +135,8 @@ en:
Error while removing network %{network_name}. %{error_message}.
delete_snapshot_error: |-
Error while deleting snapshot: %{error_message}.
tcp_tunnel_port_not_defined: |-
TCP tunnel port not defined.
states:
short_paused: |-