File: guest_network.rb

package info (click to toggle)
vagrant 2.3.7%2Bgit20230731.5fc64cde%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 17,616 kB
  • sloc: ruby: 111,820; sh: 462; makefile: 123; ansic: 34; lisp: 1
file content (125 lines) | stat: -rw-r--r-- 4,888 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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(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)
      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