landrush 1.0.0 → 1.1.0.beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -8
  3. data/.rubocop.yml +1 -0
  4. data/.travis.yml +3 -0
  5. data/CHANGELOG.md +4 -4
  6. data/CONTRIBUTING.md +54 -17
  7. data/Gemfile +4 -8
  8. data/README.md +152 -40
  9. data/features/dns_resolution.feature +9 -0
  10. data/features/landrush-ip.feature +57 -0
  11. data/features/step_definitions/ip.rb +13 -0
  12. data/landrush.gemspec +3 -1
  13. data/lib/landrush/action/setup.rb +49 -10
  14. data/lib/landrush/cap/all/read_host_visible_ip_address.rb +49 -0
  15. data/lib/landrush/config.rb +17 -11
  16. data/lib/landrush/plugin.rb +2 -2
  17. data/lib/landrush/resolver_config.rb +3 -7
  18. data/lib/landrush/server.rb +48 -22
  19. data/lib/landrush/util/retry.rb +16 -0
  20. data/lib/landrush/version.rb +1 -1
  21. data/lib/landrush/win_network_config.rb +185 -0
  22. data/lib/landrush.rb +6 -1
  23. data/test/landrush/action/setup_test.rb +44 -1
  24. data/test/landrush/action/teardown_test.rb +1 -1
  25. data/test/landrush/cap/all/read_host_visible_ip_address_test.rb +87 -0
  26. data/test/landrush/cap/linux/configured_dns_servers_test.rb +1 -1
  27. data/test/landrush/cap/linux/redirect_dns_test.rb +1 -1
  28. data/test/landrush/config_test.rb +1 -1
  29. data/test/landrush/dependent_vms_test.rb +1 -1
  30. data/test/landrush/resolver_config_test.rb +1 -3
  31. data/test/landrush/server_test.rb +1 -1
  32. data/test/landrush/store_test.rb +1 -1
  33. data/test/landrush/util/rety_test.rb +50 -0
  34. data/test/landrush/win_network_config_test.rb +70 -0
  35. data/test/support/fake_ui.rb +1 -0
  36. data/test/test_helper.rb +26 -11
  37. metadata +46 -12
  38. data/Gemfile.lock +0 -178
  39. data/examples/Vagrantfile +0 -20
  40. data/issues/vbox/Vagrantfile +0 -122
  41. data/lib/landrush/cap/linux/read_host_visible_ip_address.rb +0 -47
  42. data/lib/landrush/os.rb +0 -19
  43. data/test/landrush/cap/linux/read_host_visible_ip_address_test.rb +0 -37
@@ -15,24 +15,41 @@ module Landrush
15
15
  # This is after the middleware stack returns, which, since we're right
16
16
  # before the Network action, should mean that all interfaces are good
17
17
  # to go.
18
- record_machine_dns_entry if enabled?
19
- setup_static_dns if enabled?
18
+ post_boot_setup if enabled?
20
19
  end
21
20
 
21
+ def host_ip_address
22
+ static_private_network_ip || machine.guest.capability(:read_host_visible_ip_address)
23
+ end
24
+
25
+ private
26
+
22
27
  def pre_boot_setup
23
28
  record_dependent_vm
24
29
  add_prerequisite_network_interface
25
- setup_host_resolver
26
30
  configure_server
27
31
  start_server
28
32
  end
29
33
 
34
+ def post_boot_setup
35
+ record_machine_dns_entry
36
+ setup_static_dns
37
+ setup_host_resolver(env)
38
+ end
39
+
30
40
  def record_dependent_vm
31
41
  DependentVMs.add(machine_hostname)
32
42
  end
33
43
 
34
- def setup_host_resolver
35
- ResolverConfig.new(env).ensure_config_exists!
44
+ def setup_host_resolver(env)
45
+ if Vagrant::Util::Platform.windows?
46
+ network_config = WinNetworkConfig.new(env)
47
+ if network_config.ensure_prerequisites
48
+ network_config.update_network_adapter(host_ip_address, '127.0.0.1', config.tld)
49
+ end
50
+ elsif Vagrant::Util::Platform.darwin?
51
+ ResolverConfig.new(env).ensure_config_exists!
52
+ end
36
53
  end
37
54
 
38
55
  def add_prerequisite_network_interface
@@ -54,18 +71,25 @@ module Landrush
54
71
 
55
72
  def setup_static_dns
56
73
  config.hosts.each do |hostname, dns_value|
57
- dns_value ||= machine.guest.capability(:read_host_visible_ip_address)
74
+ dns_value ||= host_ip_address
58
75
  unless Store.hosts.has?(hostname, dns_value)
59
- info "adding static entry: #{hostname} => #{dns_value}"
76
+ info "adding static DNS entry: #{hostname} => #{dns_value}"
60
77
  Store.hosts.set hostname, dns_value
61
- Store.hosts.set(IPAddr.new(dns_value).reverse, hostname)
78
+ if ip_address?(dns_value)
79
+ reverse_dns = IPAddr.new(dns_value).reverse
80
+ info "adding static reverse DNS entry: #{reverse_dns} => #{dns_value}"
81
+ Store.hosts.set(reverse_dns, hostname)
82
+ end
62
83
  end
63
84
  end
64
85
  end
65
86
 
87
+ def ip_address?(value)
88
+ !(value =~ Resolv::IPv4::Regex).nil?
89
+ end
90
+
66
91
  def record_machine_dns_entry
67
- ip_address = machine.config.landrush.host_ip_address ||
68
- machine.guest.capability(:read_host_visible_ip_address)
92
+ ip_address = machine.config.landrush.host_ip_address || host_ip_address
69
93
 
70
94
  unless machine_hostname.match(config.tld)
71
95
  log :error, "hostname #{machine_hostname} does not match the configured TLD: #{config.tld}"
@@ -82,6 +106,21 @@ module Landrush
82
106
  def private_network_exists?
83
107
  machine.config.vm.networks.any? { |type, _| type == :private_network }
84
108
  end
109
+
110
+ # machine.config.vm.networks is an array of two elements. The first containing the type as symbol, the second is a
111
+ # hash containing other config data which varies between types
112
+ def static_private_network_ip
113
+ # select all staticlly defined private network ip
114
+ private_networks = machine.config.vm.networks.select {|network| :private_network == network[0] && !network[1][:ip].nil?}
115
+ .map {|network| network[1][:ip]}
116
+ if machine.config.landrush.host_ip_address.nil?
117
+ private_networks[0] if private_networks.length == 1
118
+ elsif private_networks.include? machine.config.landrush.host_ip_address
119
+ machine.config.landrush.host_ip_address
120
+ end
121
+ # If there is more than one private network or there is no match between config.landrush.host_ip_address
122
+ # and the discovered addresses we will pass on to read_host_visible_ip_address capability
123
+ end
85
124
  end
86
125
  end
87
126
  end
@@ -0,0 +1,49 @@
1
+ module Landrush
2
+ module Cap
3
+ module All
4
+ module ReadHostVisibleIpAddress
5
+ def self.filter_addresses(addresses)
6
+ unless @machine.config.landrush.host_interface_excludes.nil?
7
+ re = Regexp.union(@machine.config.landrush.host_interface_excludes)
8
+
9
+ addresses = addresses.select do |addr|
10
+ !addr['name'].match(re)
11
+ end
12
+ end
13
+
14
+ addresses
15
+ end
16
+
17
+ def self.read_host_visible_ip_address(machine)
18
+ @machine = machine
19
+
20
+ addr = nil
21
+ addresses = machine.guest.capability(:landrush_ip_get)
22
+
23
+ # Short circuit this one first: if an explicit interface is defined, look for it and return it if found.
24
+ # Technically, we could do a single loop, but execution time is not vital here.
25
+ # This allows us to be more accurate, especially with logging what's going on.
26
+ unless machine.config.landrush.host_interface.nil?
27
+ addr = addresses.detect { |a| a['name'] == machine.config.landrush.host_interface }
28
+
29
+ machine.env.ui.warn "[landrush] Unable to find interface #{machine.config.landrush.host_interface}" if addr.nil?
30
+ end
31
+
32
+ if addr.nil?
33
+ addresses = filter_addresses addresses
34
+
35
+ raise 'No addresses found' if addresses.empty?
36
+
37
+ addr = addresses.last
38
+ end
39
+
40
+ ip = IPAddr.new(addr['ipv4'])
41
+
42
+ machine.env.ui.info "[landrush] Using #{addr['name']} (#{addr['ipv4']})"
43
+
44
+ ip.to_s
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -6,22 +6,28 @@ module Landrush
6
6
  attr_accessor :upstream_servers
7
7
  attr_accessor :host_ip_address
8
8
  attr_accessor :guest_redirect_dns
9
+ attr_accessor :host_interface
10
+ attr_accessor :host_interface_excludes
9
11
 
10
12
  DEFAULTS = {
11
- :enabled => false,
12
- :tld => 'vagrant.test',
13
- :upstream_servers => [[:udp, '8.8.8.8', 53], [:tcp, '8.8.8.8', 53]],
14
- :host_ip_address => nil,
15
- :guest_redirect_dns => true
13
+ :enabled => false,
14
+ :tld => 'vagrant.test',
15
+ :upstream_servers => [[:udp, '8.8.8.8', 53], [:tcp, '8.8.8.8', 53]],
16
+ :host_ip_address => nil,
17
+ :guest_redirect_dns => true,
18
+ :host_interface => nil,
19
+ :host_interface_excludes => [/lo[0-9]*/, /docker[0-9]+/, /tun[0-9]+/]
16
20
  }.freeze
17
21
 
18
22
  def initialize
19
- @hosts = {}
20
- @enabled = UNSET_VALUE
21
- @tld = UNSET_VALUE
22
- @upstream_servers = UNSET_VALUE
23
- @host_ip_address = UNSET_VALUE
24
- @guest_redirect_dns = UNSET_VALUE
23
+ @hosts = {}
24
+ @enabled = UNSET_VALUE
25
+ @tld = UNSET_VALUE
26
+ @upstream_servers = UNSET_VALUE
27
+ @host_ip_address = UNSET_VALUE
28
+ @guest_redirect_dns = UNSET_VALUE
29
+ @host_interface = UNSET_VALUE
30
+ @host_interface_excludes = UNSET_VALUE
25
31
  end
26
32
 
27
33
  def enable
@@ -98,8 +98,8 @@ module Landrush
98
98
  end
99
99
 
100
100
  guest_capability('linux', 'read_host_visible_ip_address') do
101
- require_relative 'cap/linux/read_host_visible_ip_address'
102
- Cap::Linux::ReadHostVisibleIpAddress
101
+ require_relative 'cap/all/read_host_visible_ip_address'
102
+ Cap::All::ReadHostVisibleIpAddress
103
103
  end
104
104
  end
105
105
  end
@@ -29,10 +29,6 @@ module Landrush
29
29
  EOS
30
30
  end
31
31
 
32
- def osx?
33
- `uname`.chomp == 'Darwin'
34
- end
35
-
36
32
  def config_dir
37
33
  self.class.config_dir
38
34
  end
@@ -46,7 +42,7 @@ module Landrush
46
42
  end
47
43
 
48
44
  def write_config!
49
- info "Momentarily using sudo to put the host config in place..."
45
+ info 'Momentarily using sudo to put the host config in place...'
50
46
  system "#{self.class.sudo} mkdir #{config_dir}" unless config_dir.directory?
51
47
  Tempfile.open('vagrant_landrush_host_config') do |f|
52
48
  f.write(desired_contents)
@@ -58,9 +54,9 @@ module Landrush
58
54
 
59
55
  def ensure_config_exists!
60
56
  if contents_match?
61
- info "Host DNS resolver config looks good."
57
+ info 'Host DNS resolver config looks good.'
62
58
  else
63
- info "Need to configure the host."
59
+ info 'Need to configure the host.'
64
60
  write_config!
65
61
  end
66
62
  end
@@ -1,12 +1,11 @@
1
1
  require 'rubydns'
2
2
  require 'ipaddr'
3
+ require 'vagrant/util/platform'
4
+
3
5
  require_relative 'store'
4
- require_relative 'os'
5
6
 
6
7
  module Landrush
7
8
  class Server
8
- include Landrush::OS
9
-
10
9
  Name = Resolv::DNS::Name
11
10
  IN = Resolv::DNS::Resource::IN
12
11
 
@@ -31,12 +30,12 @@ module Landrush
31
30
  File.join(working_dir, 'log')
32
31
  end
33
32
 
34
- def self.log_file
33
+ def self.log_file_path
35
34
  File.join(log_directory, 'landrush.log')
36
35
  end
37
36
 
38
37
  def self.port
39
- if OS.windows?
38
+ if Vagrant::Util::Platform.windows?
40
39
  # On Windows we need to use the default DNS port, since there seems to be no way to configure it otherwise
41
40
  @port ||= 53
42
41
  else
@@ -66,14 +65,19 @@ module Landrush
66
65
 
67
66
  # Used to start the Landrush DNS server as a child process using ChildProcess gem
68
67
  def self.start
69
- ensure_path_exits(log_file)
70
-
71
- if OS.windows?
72
- pid = spawn('ruby', __FILE__, port.to_s, working_dir.to_s, :chdir => working_dir.to_path, [:out, :err] => [log_file, "w"], :new_pgroup => true)
68
+ if Vagrant::Util::Platform.windows?
69
+ # Need to handle Windows differently. Kernel.spawn fails to work, if the shell creating the process is closed.
70
+ # See https://github.com/vagrant-landrush/landrush/issues/199
71
+ info = Process.create(:command_line => "ruby #{__FILE__} #{port} #{working_dir}",
72
+ :creation_flags => Process::DETACHED_PROCESS,
73
+ :process_inherit => false,
74
+ :thread_inherit => true,
75
+ :cwd => working_dir.to_path)
76
+ pid = info.process_id
73
77
  else
74
- pid = spawn('ruby', __FILE__, port.to_s, working_dir.to_s, :chdir => working_dir.to_path, [:out, :err] => [log_file, "w"], :pgroup => true)
78
+ pid = spawn('ruby', __FILE__, port.to_s, working_dir.to_s, :chdir => working_dir.to_path, :pgroup => true)
79
+ Process.detach pid
75
80
  end
76
- Process.detach pid
77
81
 
78
82
  write_pid(pid)
79
83
  end
@@ -119,7 +123,16 @@ module Landrush
119
123
  def self.running?
120
124
  pid = read_pid
121
125
  return false if pid.nil?
122
- !!Process.kill(0, pid) rescue false
126
+ if Vagrant::Util::Platform.windows?
127
+ begin
128
+ Process.get_exitcode(pid).nil?
129
+ # Need to handle this explicitly since this error gets thrown in case we call get_exitcode with a stale pid
130
+ rescue SystemCallError => e
131
+ raise e unless e.class.name.start_with?('Errno::ENXIO')
132
+ end
133
+ else
134
+ !!Process.kill(0, pid) rescue false
135
+ end
123
136
  end
124
137
 
125
138
  def self.status
@@ -131,7 +144,7 @@ module Landrush
131
144
  else
132
145
  puts 'Daemon status: unknown'
133
146
  puts "#{pid_file} exists, but process is not running"
134
- puts "Check log file: #{log_file}"
147
+ puts "Check log file: #{log_file_path}"
135
148
  end
136
149
  end
137
150
 
@@ -140,10 +153,14 @@ module Landrush
140
153
  server.port = port
141
154
  server.working_dir = working_dir
142
155
 
143
- # Start the DNS server
144
- RubyDNS.run_server(:listen => interfaces) do
145
- @logger.level = Logger::INFO
156
+ ensure_path_exits(log_file_path)
157
+ log_file = File.open(log_file_path, 'w')
158
+ log_file.sync = true
159
+ @logger = Logger.new(log_file)
160
+ @logger.level = Logger::INFO
146
161
 
162
+ # Start the DNS server
163
+ run_dns_server(:listen => interfaces, :logger => @logger) do
147
164
  match(/.*/, IN::A) do |transaction|
148
165
  host = Store.hosts.find(transaction.name)
149
166
  if host
@@ -170,6 +187,20 @@ module Landrush
170
187
  end
171
188
  end
172
189
 
190
+ def self.run_dns_server(options = {}, &block)
191
+ server = RubyDNS::RuleBasedServer.new(options, &block)
192
+
193
+ EventMachine.run do
194
+ trap("INT") do
195
+ EventMachine.stop
196
+ end
197
+
198
+ server.run(options)
199
+ end
200
+
201
+ server.fire(:stop)
202
+ end
203
+
173
204
  def self.check_a_record(host, transaction)
174
205
  value = Store.hosts.get(host)
175
206
  if value.nil?
@@ -221,16 +252,11 @@ module Landrush
221
252
  end
222
253
 
223
254
  def self.terminate_process(pid)
224
- Process.kill("INT", pid)
225
- sleep 0.1
226
-
227
- sleep 1 if running?
228
-
229
255
  # Kill/Term loop - if the daemon didn't die easily, shoot
230
256
  # it a few more times.
231
257
  attempts = 5
232
258
  while running? && attempts > 0
233
- sig = (attempts >= 2) ? "KILL" : "TERM"
259
+ sig = (attempts >= 2) ? 'KILL' : 'TERM'
234
260
 
235
261
  puts "Sending #{sig} to process #{pid}..."
236
262
  Process.kill(sig, pid)
@@ -0,0 +1,16 @@
1
+ module Landrush
2
+ module Util
3
+ module Retry
4
+ def retry(opts=nil)
5
+ opts = {tries: 1}.merge(opts || {})
6
+ n = 0
7
+ while n < opts[:tries]
8
+ return true if yield
9
+ sleep opts[:sleep].to_f if opts[:sleep]
10
+ n += 1
11
+ end
12
+ false
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,3 +1,3 @@
1
1
  module Landrush
2
- VERSION = '1.0.0'.freeze
2
+ VERSION = '1.1.0.beta.1'.freeze
3
3
  end
@@ -0,0 +1,185 @@
1
+ # This file needs to be able to execute out of the Vagrant context. Do not require any non core or non relative files
2
+ require 'ipaddr'
3
+ require_relative 'util/retry'
4
+
5
+ # This class configures the network interface on Windows for use with the Landrush DNS server.
6
+ # It makes use of the netsh executable which is assumed to be available on the Windows host.
7
+ module Landrush
8
+ class WinNetworkConfig
9
+ include Landrush::Util::Retry
10
+
11
+ # Windows registry path under which network interface configuration is stored
12
+ INTERFACES = 'SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces'.freeze
13
+
14
+ def initialize(env={})
15
+ @env = env
16
+ end
17
+
18
+ # Checks that all required tools are on the PATH and that the Wired AutoConfig service is started
19
+ def ensure_prerequisites
20
+ return false unless command_found('netsh')
21
+ return false unless command_found('net')
22
+ return false unless command_found('reg')
23
+
24
+ unless wired_autoconfig_service_running?
25
+ info('starting \'Wired AutoConfig\' service')
26
+ if self.class.admin_mode?
27
+ `net start dot3svc`
28
+ else
29
+ require 'win32ole'
30
+ shell = WIN32OLE.new('Shell.Application')
31
+ shell.ShellExecute('net', 'start dot3svc', nil, 'runas', 1)
32
+ end
33
+ service_has_started = self.retry(tries: 5, sleep: 1) do
34
+ wired_autoconfig_service_running?
35
+ end
36
+ unless service_has_started
37
+ info('Unable to start \'Wired AutoConfig\' service. Unable to configure DNS on host. Try manual configuration.')
38
+ return false
39
+ end
40
+ info('\'Wired AutoConfig\' service has started.')
41
+ end
42
+ true
43
+ end
44
+
45
+ # Does the actual update of the network configuration
46
+ def update_network_adapter(ip, name_server, domain)
47
+ # Need to defer loading to ensure cross OS compatibility
48
+ require 'win32/registry'
49
+ ensure_admin_privileges(__FILE__.to_s, ip, name_server, domain)
50
+
51
+ network_name = get_network_name(ip)
52
+ if network_name.nil?
53
+ info("unable to determine network interface for #{ip}. DNS on host cannot be configured. Try manual configuration.")
54
+ return
55
+ else
56
+ info("adding Landrush'es DNS server to network '#{network_name}' using DNS IP '#{ip}'' and search domain '#{domain}'")
57
+ end
58
+ network_guid = get_guid(network_name)
59
+ if network_guid.nil?
60
+ info("unable to determine network GUID for #{ip}. DNS on host cannot be configured. Try manual configuration.")
61
+ return
62
+ end
63
+ interface_path = INTERFACES + "\\{#{network_guid}}"
64
+ Win32::Registry::HKEY_LOCAL_MACHINE.open(interface_path, Win32::Registry::KEY_ALL_ACCESS) do |reg|
65
+ reg['NameServer'] = name_server
66
+ reg['Domain'] = domain
67
+ end
68
+ end
69
+
70
+ # If this registry query succeeds we assume we have Admin rights
71
+ # http://stackoverflow.com/questions/8268154/run-ruby-script-in-elevated-mode/27954953
72
+ def self.admin_mode?
73
+ (`reg query HKU\\S-1-5-19 2>&1` =~ /ERROR/).nil?
74
+ end
75
+
76
+ private
77
+
78
+ # Given a network name (as displayed on 'Control Panel\Network and Internet\Network Connections'),
79
+ # determines the GUID of this network interface using 'netsh'.
80
+ #
81
+ # To make this work the "Wired Autoconfig" service must be started (go figure).
82
+ #
83
+ # Output of netsh command which is being processed:
84
+ #
85
+ # There are 4 interfaces on the system:
86
+ #
87
+ # Name : Ethernet
88
+ # Description : Intel(R) Ethernet Connection (3) I218-LM
89
+ # GUID : fd9270f6-aff6-4f24-bc4a-1f90c032d5c3
90
+ # Physical Address : 50-7B-9D-AB-25-1D
91
+ # \n\n
92
+ # ...
93
+ def get_guid(network_name)
94
+ cmd_out = `netsh lan show interfaces`
95
+ interface_details = cmd_out.split(/\n\n/).select { |settings| settings.match(/#{Regexp.quote(network_name)}/m) }
96
+ return nil if interface_details.empty?
97
+ interface_details[0].split(/\n/)[2].match(/.*:(.*)/).captures[0].strip
98
+ end
99
+
100
+ # Given an IP determines the network name, if any. Uses netsh which generates output like this:
101
+ #
102
+ # ...
103
+ # \n\n
104
+ # Configuration for interface "Ethernet 2"
105
+ # DHCP enabled: Yes
106
+ # IP Address: 10.10.10.1
107
+ # Subnet Prefix: 10.10.10.0/24 (mask 255.255.255.0)
108
+ # InterfaceMetric: 10
109
+ # DNS servers configured through DHCP: None
110
+ # Register with which suffix: Primary only
111
+ # WINS servers configured through DHCP: None
112
+ # \n\n
113
+ # ...
114
+ def get_network_name(ip)
115
+ cmd_out = `netsh interface ip show config`
116
+ network_details = cmd_out.split(/\n\n/).select do |settings|
117
+ begin
118
+ lines = settings.split(/\n/).reject(&:empty?)
119
+ subnet = lines[3]
120
+ next false unless subnet =~ /Subnet Prefix/
121
+
122
+ mask = IPAddr.new(subnet.match(%r{.* (\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}/\d{1,3}).*}).captures[0])
123
+ address = IPAddr.new(ip)
124
+
125
+ mask.include?(address)
126
+ rescue
127
+ false
128
+ end
129
+ end
130
+ return nil if network_details[0].nil?
131
+ network_details[0].split(/\n/)[0].match(/Configuration for interface "(.*)"/).captures[0].strip
132
+ end
133
+
134
+ # Makes sure that we have admin privileges and if nor starts a new shell with the required
135
+ # privileges
136
+ def ensure_admin_privileges(file, *args)
137
+ unless self.class.admin_mode?
138
+ require 'win32ole'
139
+ shell = WIN32OLE.new('Shell.Application')
140
+ shell.ShellExecute('ruby', "#{file} #{args.join(' ')}", nil, 'runas', 1)
141
+ # need to exit current execution, changes will occur in new environment
142
+ exit
143
+ end
144
+ end
145
+
146
+ def info(msg)
147
+ @env[:ui].info("[landrush] #{msg}") unless @env.nil?
148
+ end
149
+
150
+ def wired_autoconfig_service_running?
151
+ cmd_out = `net start`
152
+ cmd_out =~ /Wired AutoConfig/m
153
+ end
154
+
155
+ def command_found(cmd)
156
+ if which(cmd).nil?
157
+ info("Cannot find '#{cmd}' on the PATH. Unable to configure DNS. Try manual configuration.")
158
+ false
159
+ else
160
+ true
161
+ end
162
+ end
163
+
164
+ # Cross-platform way of finding an executable in the $PATH.
165
+ #
166
+ # which('ruby') #=> /usr/bin/ruby
167
+ def which(cmd)
168
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
169
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
170
+ exts.each do |ext|
171
+ exe = File.join(path, "#{cmd}#{ext}")
172
+ return exe if File.executable?(exe) && !File.directory?(exe)
173
+ end
174
+ end
175
+ nil
176
+ end
177
+ end
178
+ end
179
+
180
+ # Only run the following code when this file is the main file being run
181
+ # instead of having been required or loaded by another file
182
+ if __FILE__ == $0
183
+ config = Landrush::WinNetworkConfig.new nil
184
+ config.update_network_adapter(ARGV[0], ARGV[1], ARGV[2])
185
+ end
data/lib/landrush.rb CHANGED
@@ -4,12 +4,17 @@ rescue LoadError
4
4
  raise 'The Vagrant landrush plugin must be run within Vagrant.'
5
5
  end
6
6
 
7
+ # Only load the gem on Windows since it replaces some methods in Ruby's Process class
8
+ # Also load before Process.uid is called the first time by Vagrant
9
+ require 'win32/process' if Vagrant::Util::Platform.windows?
10
+
7
11
  require 'rubydns'
8
- require 'ipaddr'
9
12
 
10
13
  require 'landrush/dependent_vms'
11
14
  require 'landrush/plugin'
12
15
  require 'landrush/resolver_config'
16
+ require 'landrush/win_network_config'
13
17
  require 'landrush/server'
14
18
  require 'landrush/store'
15
19
  require 'landrush/version'
20
+ require 'landrush-ip'