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.
- checksums.yaml +4 -4
- data/.gitignore +8 -8
- data/.rubocop.yml +1 -0
- data/.travis.yml +3 -0
- data/CHANGELOG.md +4 -4
- data/CONTRIBUTING.md +54 -17
- data/Gemfile +4 -8
- data/README.md +152 -40
- data/features/dns_resolution.feature +9 -0
- data/features/landrush-ip.feature +57 -0
- data/features/step_definitions/ip.rb +13 -0
- data/landrush.gemspec +3 -1
- data/lib/landrush/action/setup.rb +49 -10
- data/lib/landrush/cap/all/read_host_visible_ip_address.rb +49 -0
- data/lib/landrush/config.rb +17 -11
- data/lib/landrush/plugin.rb +2 -2
- data/lib/landrush/resolver_config.rb +3 -7
- data/lib/landrush/server.rb +48 -22
- data/lib/landrush/util/retry.rb +16 -0
- data/lib/landrush/version.rb +1 -1
- data/lib/landrush/win_network_config.rb +185 -0
- data/lib/landrush.rb +6 -1
- data/test/landrush/action/setup_test.rb +44 -1
- data/test/landrush/action/teardown_test.rb +1 -1
- data/test/landrush/cap/all/read_host_visible_ip_address_test.rb +87 -0
- data/test/landrush/cap/linux/configured_dns_servers_test.rb +1 -1
- data/test/landrush/cap/linux/redirect_dns_test.rb +1 -1
- data/test/landrush/config_test.rb +1 -1
- data/test/landrush/dependent_vms_test.rb +1 -1
- data/test/landrush/resolver_config_test.rb +1 -3
- data/test/landrush/server_test.rb +1 -1
- data/test/landrush/store_test.rb +1 -1
- data/test/landrush/util/rety_test.rb +50 -0
- data/test/landrush/win_network_config_test.rb +70 -0
- data/test/support/fake_ui.rb +1 -0
- data/test/test_helper.rb +26 -11
- metadata +46 -12
- data/Gemfile.lock +0 -178
- data/examples/Vagrantfile +0 -20
- data/issues/vbox/Vagrantfile +0 -122
- data/lib/landrush/cap/linux/read_host_visible_ip_address.rb +0 -47
- data/lib/landrush/os.rb +0 -19
- 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
|
-
|
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
|
-
|
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 ||=
|
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
|
-
|
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
|
data/lib/landrush/config.rb
CHANGED
@@ -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
|
12
|
-
:tld
|
13
|
-
:upstream_servers
|
14
|
-
:host_ip_address
|
15
|
-
:guest_redirect_dns
|
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
|
21
|
-
@tld
|
22
|
-
@upstream_servers
|
23
|
-
@host_ip_address
|
24
|
-
@guest_redirect_dns
|
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
|
data/lib/landrush/plugin.rb
CHANGED
@@ -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/
|
102
|
-
Cap::
|
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
|
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
|
57
|
+
info 'Host DNS resolver config looks good.'
|
62
58
|
else
|
63
|
-
info
|
59
|
+
info 'Need to configure the host.'
|
64
60
|
write_config!
|
65
61
|
end
|
66
62
|
end
|
data/lib/landrush/server.rb
CHANGED
@@ -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.
|
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
|
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
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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,
|
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
|
-
|
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: #{
|
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
|
-
|
144
|
-
|
145
|
-
|
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) ?
|
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
|
data/lib/landrush/version.rb
CHANGED
@@ -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'
|