Module: VagrantPlugins::QEMU::Network

Defined in:
lib/vagrant-qemu/network.rb,
lib/vagrant-qemu/network/tap.rb,
lib/vagrant-qemu/network/base.rb,
lib/vagrant-qemu/network/vmnet.rb,
lib/vagrant-qemu/network/socket.rb,
lib/vagrant-qemu/network/socket_vmnet.rb

Defined Under Namespace

Classes: Base, Socket, SocketVmnet, Tap, Vmnet

Class Method Summary collapse

Class Method Details

.auto_detectBase

Auto-detect the best backend for the current platform.

Returns:



34
35
36
37
38
39
40
41
42
43
# File 'lib/vagrant-qemu/network.rb', line 34

def self.auto_detect
  case RbConfig::CONFIG['host_os']
  when /darwin/
    Vmnet.new
  when /linux/
    Tap.new
  else
    Socket.new
  end
end

.backend_for(net_mode) ⇒ Base

Select the appropriate network backend based on net_mode and platform.

Parameters:

  • net_mode (Symbol)

    :auto, :vmnet_shared, :vmnet_host, :vmnet_bridged, :tap, :socket, :socket_vmnet

Returns:

  • (Base)

    a network backend instance



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/vagrant-qemu/network.rb', line 15

def self.backend_for(net_mode)
  case net_mode
  when :vmnet_shared, :vmnet_host, :vmnet_bridged
    Vmnet.new
  when :tap
    Tap.new
  when :socket
    Socket.new
  when :socket_vmnet
    SocketVmnet.new
  when :auto
    auto_detect
  else
    raise Errors::ConfigError, err: "Unknown net_mode: #{net_mode}"
  end
end

.build_network_config(mac0:, mac1:, ip:, netmask: "255.255.255.0") ⇒ String

Build cloud-init network-config v2 YAML for dual-NIC setup. Only called when advanced_network is enabled and private_network is configured.

Parameters:

  • mac0 (String)

    MAC of user-mode NIC (DHCP)

  • mac1 (String)

    MAC of advanced network NIC

  • ip (String)

    static IP for the advanced NIC (e.g. "192.168.105.10")

  • netmask (String) (defaults to: "255.255.255.0")

    netmask (e.g. "255.255.255.0")

Returns:

  • (String)

    YAML string



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/vagrant-qemu/network.rb', line 104

def self.build_network_config(mac0:, mac1:, ip:, netmask: "255.255.255.0")
  require 'ipaddr'
  require 'yaml'

  prefix = IPAddr.new(netmask).to_i.to_s(2).count("1")

  config = {
    "network" => {
      "version" => 2,
      "ethernets" => {
        "user-nic" => {
          "match" => { "macaddress" => mac0 },
          "dhcp4" => true
        },
        "private-nic" => {
          "match" => { "macaddress" => mac1 },
          "addresses" => ["#{ip}/#{prefix}"]
        }
      }
    }
  }

  config.to_yaml
end

.generate_mac(vm_id, nic_index) ⇒ String

Generate a deterministic MAC address from vm_id and NIC index. Uses 52:54:00 prefix (QEMU's OUI).

Parameters:

  • vm_id (String)
  • nic_index (Integer)

Returns:

  • (String)

    MAC address like "52:54:00:ab:cd:ef"



79
80
81
82
83
# File 'lib/vagrant-qemu/network.rb', line 79

def self.generate_mac(vm_id, nic_index)
  require 'digest'
  hash = Digest::MD5.hexdigest("#{vm_id}-#{nic_index}")
  "52:54:00:#{hash[0..1]}:#{hash[2..3]}:#{hash[4..5]}"
end

.nic_macs(vm_id, pn) ⇒ Array(String, String)

MAC pair for the dual-NIC setup; NIC 1 honors a user-specified MAC. Single source of truth so the QEMU command line (driver) and the cloud-init network-config (CloudInitNetwork action) never diverge.

Parameters:

  • vm_id (String)
  • pn (Hash, nil)

    first private_network options

Returns:

  • (Array(String, String))

    [mac0, mac1]



92
93
94
# File 'lib/vagrant-qemu/network.rb', line 92

def self.nic_macs(vm_id, pn)
  [generate_mac(vm_id, 0), (pn && pn[:mac]) || generate_mac(vm_id, 1)]
end

.qemu_supports_stream?(qemu_binary) ⇒ Boolean?

Whether the QEMU binary has the native stream netdev (QEMU >= 7.2), so socket_vmnet can connect to the daemon's unix socket directly instead of going through the socket_vmnet_client wrapper.

Probes <qemu> -M none -netdev help and looks for a stream line on stdout. Cached per binary.

Tri-state so the driver can honor the design's fallback direction:

true  -- probe ran, stream present  -> use stream
false -- probe ran, stream absent    -> use the wrapper (old QEMU)
nil   -- probe could not run (rare)  -> driver defaults to stream

Parameters:

  • qemu_binary (String)

    path/name of the qemu-system-* binary

Returns:

  • (Boolean, nil)


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

def self.qemu_supports_stream?(qemu_binary)
  @stream_support ||= {}
  return @stream_support[qemu_binary] if @stream_support.key?(qemu_binary)

  result =
    begin
      out = ::Vagrant::Util::Subprocess.execute(qemu_binary, "-M", "none", "-netdev", "help")
      out.exit_code == 0 ? out.stdout.lines.any? { |l| l.strip == "stream" } : nil
    rescue StandardError
      nil
    end
  @stream_support[qemu_binary] = result
end