guests/windows: configure networks
This commit is contained in:
parent
d86a9ecade
commit
d600e83e6d
|
@ -1,10 +1,6 @@
|
|||
require "log4r"
|
||||
|
||||
require_relative '../../communication/guestnetwork'
|
||||
require_relative '../../communication/winrmshell'
|
||||
require_relative '../../errors'
|
||||
require_relative '../../helper'
|
||||
require_relative '../../windows_machine'
|
||||
require_relative "../guest_network"
|
||||
|
||||
module VagrantPlugins
|
||||
module GuestWindows
|
||||
|
@ -15,19 +11,20 @@ module VagrantPlugins
|
|||
def self.configure_networks(machine, networks)
|
||||
@@logger.debug("Networks: #{networks.inspect}")
|
||||
|
||||
windows_machine = VagrantWindows::WindowsMachine.new(machine)
|
||||
guest_network = VagrantWindows::Communication::GuestNetwork.new(windows_machine.winrmshell)
|
||||
if windows_machine.is_vmware?()
|
||||
@@logger.warn('Configuring secondary network adapters through VMware is not yet supported.')
|
||||
@@logger.warn('You will need to manually configure the network adapter.')
|
||||
guest_network = GuestNetwork.new(machine.communicate.shell)
|
||||
if machine.provider_name.to_s.start_with?("vmware")
|
||||
machine.ui.warn("Configuring secondary network adapters through VMware ")
|
||||
machine.ui.warn("on Windows is not yet supported. You will need to manually")
|
||||
machine.ui.warn("configure the network adapter.")
|
||||
else
|
||||
vm_interface_map = create_vm_interface_map(windows_machine, guest_network)
|
||||
vm_interface_map = create_vm_interface_map(machine, guest_network)
|
||||
networks.each do |network|
|
||||
interface = vm_interface_map[network[:interface]+1]
|
||||
if interface.nil?
|
||||
@@logger.warn("Could not find interface for network #{network.inspect}")
|
||||
next
|
||||
end
|
||||
|
||||
network_type = network[:type].to_sym
|
||||
if network_type == :static
|
||||
guest_network.configure_static_interface(
|
||||
|
@ -40,19 +37,27 @@ module VagrantPlugins
|
|||
interface[:index],
|
||||
interface[:net_connection_id])
|
||||
else
|
||||
raise WindowsError, "#{network_type} network type is not supported, try static or dhcp"
|
||||
raise "#{network_type} network type is not supported, try static or dhcp"
|
||||
end
|
||||
end
|
||||
end
|
||||
guest_network.set_all_networks_to_work() if windows_machine.windows_config.set_work_network
|
||||
|
||||
if machine.config.windows.set_work_network
|
||||
guest_network.set_all_networks_to_work
|
||||
end
|
||||
end
|
||||
|
||||
#{1=>{:name=>"Local Area Connection", :mac_address=>"0800275FAC5B", :interface_index=>"11", :index=>"7"}}
|
||||
def self.create_vm_interface_map(windows_machine, guest_network)
|
||||
vm_interface_map = {}
|
||||
driver_mac_address = windows_machine.read_mac_addresses.invert
|
||||
def self.create_vm_interface_map(machine, guest_network)
|
||||
if !machine.provider.capability?(:nic_mac_addresses)
|
||||
raise Errors::CantReadMACAddresses,
|
||||
provider: machine.provider_name.to_s
|
||||
end
|
||||
|
||||
driver_mac_address = machine.provider.capability(:nic_mac_addresses)
|
||||
@@logger.debug("mac addresses: #{driver_mac_address.inspect}")
|
||||
guest_network.network_adapters().each do |nic|
|
||||
|
||||
vm_interface_map = {}
|
||||
guest_network.network_adapters.each do |nic|
|
||||
@@logger.debug("nic: #{nic.inspect}")
|
||||
naked_mac = nic[:mac_address].gsub(':','')
|
||||
if driver_mac_address[naked_mac]
|
||||
|
@ -63,6 +68,7 @@ module VagrantPlugins
|
|||
:index => nic[:index] }
|
||||
end
|
||||
end
|
||||
|
||||
@@logger.debug("vm_interface_map: #{vm_interface_map.inspect}")
|
||||
vm_interface_map
|
||||
end
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
module VagrantPlugins
|
||||
module GuestWindows
|
||||
module Errors
|
||||
# A convenient superclass for all our errors.
|
||||
class WindowsError < Vagrant::Errors::VagrantError
|
||||
error_namespace("vagrant_windows.errors")
|
||||
end
|
||||
|
||||
class CantReadMACAddresses < WindowsError
|
||||
error_key(:cant_read_mac_addresses)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,125 @@
|
|||
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(winrmshell)
|
||||
@logger = Log4r::Logger.new("vagrant::windows::guestnetwork")
|
||||
@winrmshell = winrmshell
|
||||
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)
|
||||
has_dhcp_enabled = false
|
||||
cmd = "Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter \"Index=#{nic_index} and DHCPEnabled=True\""
|
||||
@winrmshell.powershell(cmd) do |type, line|
|
||||
has_dhcp_enabled = !line.nil?
|
||||
end
|
||||
@logger.debug("NIC #{nic_index} has DHCP enabled: #{has_dhcp_enabled}")
|
||||
has_dhcp_enabled
|
||||
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"
|
||||
@winrmshell.powershell(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}"
|
||||
@winrmshell.powershell(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"))
|
||||
@winrmshell.powershell(command)
|
||||
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 = ''
|
||||
@winrmshell.powershell(PS_GET_WSMAN_VER) 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
|
||||
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa394216(v=vs.85).aspx
|
||||
adapters = @winrmshell.wql(WQL_NET_ADAPTERS_V2)[: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"))
|
||||
output = ""
|
||||
@winrmshell.powershell(command) 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
|
|
@ -2,6 +2,8 @@ require "vagrant"
|
|||
|
||||
module VagrantPlugins
|
||||
module GuestWindows
|
||||
autoload :Errors, File.expand_path("../errors", __FILE__)
|
||||
|
||||
class Plugin < Vagrant.plugin("2")
|
||||
name "Windows guest."
|
||||
description "Windows guest support."
|
||||
|
@ -13,6 +15,7 @@ module VagrantPlugins
|
|||
|
||||
guest("windows") do
|
||||
require_relative "guest"
|
||||
init!
|
||||
Guest
|
||||
end
|
||||
|
||||
|
@ -45,6 +48,16 @@ module VagrantPlugins
|
|||
require_relative "cap/mount_shared_folder"
|
||||
Cap::MountSharedFolder
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def self.init!
|
||||
return if defined?(@_init)
|
||||
I18n.load_path << File.expand_path(
|
||||
"templates/locales/guest_windows.yml", Vagrant.source_root)
|
||||
I18n.reload!
|
||||
@_init = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
# Get network connections
|
||||
$networkListManager = [Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]"{DCB00C01-570F-4A9B-8D69-199FDBA5723B}"))
|
||||
$connections = $networkListManager.GetNetworkConnections()
|
||||
|
||||
# Set network location to Private for all networks
|
||||
$connections | % {$_.GetNetwork().SetCategory(1)}
|
|
@ -0,0 +1,11 @@
|
|||
$adapters = get-ciminstance win32_networkadapter -filter "macaddress is not null"
|
||||
$processed = @()
|
||||
foreach ($adapter in $adapters) {
|
||||
$Processed += new-object PSObject -Property @{
|
||||
mac_address = $adapter.macaddress
|
||||
net_connection_id = $adapter.netconnectionid
|
||||
interface_index = $adapter.interfaceindex
|
||||
index = $adapter.index
|
||||
}
|
||||
}
|
||||
convertto-json -inputobject $processed
|
|
@ -15,6 +15,13 @@ module VagrantPlugins
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Reads the network interface card MAC addresses and returns them.
|
||||
#
|
||||
# @return [Hash<String, String>] Adapter => MAC address
|
||||
def self.nic_mac_addresses(machine)
|
||||
machine.provider.driver.read_mac_addresses
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -28,6 +28,11 @@ module VagrantPlugins
|
|||
require_relative "cap"
|
||||
Cap
|
||||
end
|
||||
|
||||
provider_capability(:virtualbox, :nic_mac_addresses) do
|
||||
require_relative "cap"
|
||||
Cap
|
||||
end
|
||||
end
|
||||
|
||||
autoload :Action, File.expand_path("../action", __FILE__)
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
en:
|
||||
vagrant_winrm:
|
||||
errors:
|
||||
cant_read_mac_addresses: |-
|
||||
The provider being used to start Windows ('%{provider}')
|
||||
doesn't support the "nic_mac_addresses" capability which is required
|
||||
for advanced networking to work with Windows guests. Please inform
|
||||
the author of the provider to add this feature.
|
||||
|
||||
Until then, you must remove any networking configurations other
|
||||
than forwarded ports from your Vagrantfile for Vagrant to continue.
|
Loading…
Reference in New Issue