vagrant/plugins/guests/windows/guest_network.rb

126 lines
4.8 KiB
Ruby

require "log4r"
module VagrantPlugins
module GuestWindows
# Manages the remote Windows guest network.
class GuestNetwork
PS_GET_WSMAN_VER = '((test-wsman).productversion.split(" ") | select -last 1).split("\.")[0]'
WQL_NET_ADAPTERS_V2 = 'SELECT * FROM Win32_NetworkAdapter WHERE MACAddress IS NOT NULL'
def initialize(communicator)
@logger = Log4r::Logger.new("vagrant::windows::guestnetwork")
@communicator = communicator
end
# Returns an array of all NICs on the guest. Each array entry is a
# Hash of the NICs properties.
#
# @return [Array]
def network_adapters
wsman_version == 2? network_adapters_v2_winrm : network_adapters_v3_winrm
end
# Checks to see if the specified NIC is currently configured for DHCP.
#
# @return [Boolean]
def is_dhcp_enabled(nic_index)
cmd = <<-EOH
if (Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "Index=#{nic_index} and DHCPEnabled=True") {
exit 0
}
exit 1
EOH
@communicator.test(cmd, { shell: :powershell })
end
# Configures the specified interface for DHCP
#
# @param [Integer] The interface index.
# @param [String] The unique name of the NIC, such as 'Local Area Connection'.
def configure_dhcp_interface(nic_index, net_connection_id)
@logger.info("Configuring NIC #{net_connection_id} for DHCP")
if !is_dhcp_enabled(nic_index)
netsh = "netsh interface ip set address \"#{net_connection_id}\" dhcp"
@communicator.execute(netsh)
end
end
# Configures the specified interface using a static address
#
# @param [Integer] The interface index.
# @param [String] The unique name of the NIC, such as 'Local Area Connection'.
# @param [String] The static IP address to assign to the specified NIC.
# @param [String] The network mask to use with the static IP.
def configure_static_interface(nic_index, net_connection_id, ip, netmask)
@logger.info("Configuring NIC #{net_connection_id} using static ip #{ip}")
#netsh interface ip set address "Local Area Connection 2" static 192.168.33.10 255.255.255.0
netsh = "netsh interface ip set address \"#{net_connection_id}\" static #{ip} #{netmask}"
@communicator.execute(netsh)
end
# Sets all networks on the guest to 'Work Network' mode. This is
# to allow guest access from the host via a private IP on Win7
# https://github.com/WinRb/vagrant-windows/issues/63
def set_all_networks_to_work
@logger.info("Setting all networks to 'Work Network'")
command = File.read(File.expand_path("../scripts/set_work_network.ps1", __FILE__))
@communicator.execute(command, { shell: :powershell })
end
protected
# Checks the WinRS version on the guest. Usually 2 on Windows 7/2008
# and 3 on Windows 8/2012.
#
# @return [Integer]
def wsman_version
@logger.debug("querying WSMan version")
version = ''
@communicator.execute(PS_GET_WSMAN_VER, { shell: :powershell }) do |type, line|
version = version + "#{line}" if type == :stdout && !line.nil?
end
@logger.debug("wsman version: #{version}")
Integer(version)
end
# Returns an array of all NICs on the guest. Each array entry is a
# Hash of the NICs properties. This method should only be used on
# guests that have WinRS version 2.
#
# @return [Array]
def network_adapters_v2_winrm
@logger.debug("querying network adapters")
# Get all NICs that have a MAC address
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa394216(v=vs.85).aspx
adapters = @communicator.execute(WQL_NET_ADAPTERS_V2, { shell: :wql } )[:win32_network_adapter]
@logger.debug("#{adapters.inspect}")
return adapters
end
# Returns an array of all NICs on the guest. Each array entry is a
# Hash of the NICs properties. This method should only be used on
# guests that have WinRS version 3.
#
# This method is a workaround until the WinRM gem supports WinRS version 3.
#
# @return [Array]
def network_adapters_v3_winrm
command = File.read(File.expand_path("../scripts/winrs_v3_get_adapters.ps1", __FILE__))
output = ""
@communicator.execute(command, { shell: :powershell }) do |type, line|
output = output + "#{line}" if type == :stdout && !line.nil?
end
adapters = []
JSON.parse(output).each do |nic|
adapters << nic.inject({}){ |memo,(k,v)| memo[k.to_sym] = v; memo }
end
@logger.debug("#{adapters.inspect}")
return adapters
end
end
end
end