vagrant-windows 1.2.0 → 1.3.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.
- data/.DS_Store +0 -0
- data/CHANGELOG.md +38 -0
- data/Gemfile +2 -1
- data/LICENSE +13 -0
- data/README.md +78 -110
- data/coverage/.last_run.json +1 -1
- data/coverage/.resultset.json +685 -210
- data/coverage/index.html +5333 -2355
- data/init.pp +5 -0
- data/lib/vagrant-windows/communication/winrmcommunicator.rb +49 -61
- data/lib/vagrant-windows/communication/winrmfinder.rb +23 -17
- data/lib/vagrant-windows/communication/winrmshell.rb +34 -16
- data/lib/vagrant-windows/communication/winrmshell_factory.rb +34 -0
- data/lib/vagrant-windows/config/winrm.rb +1 -2
- data/lib/vagrant-windows/errors.rb +2 -2
- data/lib/vagrant-windows/guest/cap/configure_networks.rb +33 -29
- data/lib/vagrant-windows/guest/cap/halt.rb +4 -0
- data/lib/vagrant-windows/guest/cap/mount_shared_folder.rb +31 -0
- data/lib/vagrant-windows/guest/windows.rb +13 -11
- data/lib/vagrant-windows/helper.rb +22 -1
- data/lib/vagrant-windows/monkey_patches/plugins/provisioners/chef/provisioner/chef_solo.rb +17 -5
- data/lib/vagrant-windows/monkey_patches/plugins/provisioners/puppet/provisioner/puppet.rb +54 -17
- data/lib/vagrant-windows/monkey_patches/plugins/provisioners/shell/provisioner.rb +36 -22
- data/lib/vagrant-windows/plugin.rb +4 -4
- data/lib/vagrant-windows/scripts/cheftask.ps1.erb +13 -12
- data/lib/vagrant-windows/scripts/cheftask.xml.erb +1 -1
- data/lib/vagrant-windows/scripts/cheftaskrun.ps1.erb +3 -1
- data/lib/vagrant-windows/scripts/{mount_volume.vmware.ps1.erb → mount_volume.ps1.erb} +2 -1
- data/lib/vagrant-windows/scripts/reboot_detect.ps1 +43 -0
- data/lib/vagrant-windows/version.rb +1 -1
- data/lib/vagrant-windows/windows_machine.rb +87 -0
- data/locales/en.yml +2 -5
- data/puppet-3.3.2.msi +0 -0
- data/spec/vagrant-windows/guestnetwork_spec.rb +14 -2
- data/spec/vagrant-windows/helper_spec.rb +1 -0
- data/spec/vagrant-windows/mount_shared_folder_spec.rb +34 -0
- data/spec/vagrant-windows/windows_config_spec.rb +26 -0
- data/spec/vagrant-windows/windows_machine_spec.rb +65 -0
- data/spec/vagrant-windows/{config_spec.rb → winrm_config_spec.rb} +2 -28
- data/spec/vagrant-windows/winrmcommunicator_spec.rb +29 -8
- data/spec/vagrant-windows/winrmfinder_spec.rb +42 -0
- data/spec/vagrant-windows/winrmshell_spec.rb +39 -0
- data/test.ps1 +1 -0
- data/vagrant-windows.gemspec +6 -5
- metadata +59 -19
- checksums.yaml +0 -7
- data/lib/vagrant-windows/guest/cap/mount_virtualbox_shared_folder.rb +0 -17
- data/lib/vagrant-windows/guest/cap/mount_vmware_shared_folder.rb +0 -15
- data/lib/vagrant-windows/scripts/mount_volume.virtualbox.ps1.erb +0 -49
data/init.pp
ADDED
|
@@ -1,37 +1,36 @@
|
|
|
1
1
|
require 'timeout'
|
|
2
2
|
require 'log4r'
|
|
3
|
-
require_relative '
|
|
3
|
+
require_relative 'winrmshell_factory'
|
|
4
4
|
require_relative 'winrmshell'
|
|
5
5
|
require_relative 'winrmfinder'
|
|
6
|
+
require_relative '../errors'
|
|
7
|
+
require_relative '../windows_machine'
|
|
6
8
|
|
|
7
9
|
module VagrantWindows
|
|
8
10
|
module Communication
|
|
9
|
-
# Provides communication
|
|
11
|
+
# Provides communication channel for Vagrant commands via WinRM.
|
|
10
12
|
class WinRMCommunicator < Vagrant.plugin("2", :communicator)
|
|
11
|
-
|
|
12
|
-
attr_reader :logger
|
|
13
|
-
attr_reader :machine
|
|
14
|
-
attr_reader :winrm_finder
|
|
15
13
|
|
|
16
14
|
def self.match?(machine)
|
|
17
|
-
|
|
15
|
+
VagrantWindows::WindowsMachine.is_windows?(machine)
|
|
18
16
|
end
|
|
19
17
|
|
|
20
18
|
def initialize(machine)
|
|
21
|
-
@
|
|
19
|
+
@windows_machine = VagrantWindows::WindowsMachine.new(machine)
|
|
20
|
+
@winrm_shell_factory = WinRMShellFactory.new(@windows_machine, WinRMFinder.new(@windows_machine))
|
|
21
|
+
|
|
22
22
|
@logger = Log4r::Logger.new("vagrant_windows::communication::winrmcommunicator")
|
|
23
23
|
@logger.debug("initializing WinRMCommunicator")
|
|
24
|
-
@winrm_finder = WinRMFinder.new(machine)
|
|
25
24
|
end
|
|
26
25
|
|
|
27
26
|
def ready?
|
|
28
|
-
logger.debug("Checking whether WinRM is ready...")
|
|
27
|
+
@logger.debug("Checking whether WinRM is ready...")
|
|
29
28
|
|
|
30
|
-
Timeout.timeout(@
|
|
31
|
-
|
|
29
|
+
Timeout.timeout(@windows_machine.winrm_config.timeout) do
|
|
30
|
+
winrmshell.powershell("hostname")
|
|
32
31
|
end
|
|
33
32
|
|
|
34
|
-
logger.info("WinRM is ready!")
|
|
33
|
+
@logger.info("WinRM is ready!")
|
|
35
34
|
return true
|
|
36
35
|
|
|
37
36
|
rescue Vagrant::Errors::VagrantError => e
|
|
@@ -42,79 +41,68 @@ module VagrantWindows
|
|
|
42
41
|
end
|
|
43
42
|
|
|
44
43
|
def execute(command, opts={}, &block)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
opts = {
|
|
45
|
+
:error_check => true,
|
|
46
|
+
:error_class => VagrantWindows::Errors::WinRMExecutionError,
|
|
47
|
+
:error_key => :winrm_execution_error,
|
|
48
|
+
:command => command,
|
|
49
|
+
:shell => :powershell
|
|
50
|
+
}.merge(opts || {})
|
|
51
|
+
exit_status = do_execute(command, opts[:shell], &block)
|
|
52
|
+
if opts[:error_check] && exit_status != 0
|
|
53
|
+
raise_execution_error(opts, exit_status)
|
|
50
54
|
end
|
|
55
|
+
exit_status
|
|
51
56
|
end
|
|
52
57
|
alias_method :sudo, :execute
|
|
53
58
|
|
|
54
59
|
def test(command, opts=nil)
|
|
60
|
+
@logger.debug("Testing: #{command}")
|
|
61
|
+
|
|
55
62
|
# HACK: to speed up Vagrant 1.2 OS detection, skip checking for *nix OS
|
|
56
63
|
return false unless (command =~ /^uname|^cat \/etc|^cat \/proc|grep 'Fedora/).nil?
|
|
57
|
-
|
|
64
|
+
|
|
65
|
+
opts = { :error_check => false }.merge(opts || {})
|
|
66
|
+
execute(command, opts) == 0
|
|
58
67
|
end
|
|
59
68
|
|
|
60
69
|
def upload(from, to)
|
|
61
70
|
@logger.debug("Uploading: #{from} to #{to}")
|
|
62
|
-
|
|
63
|
-
file_name = (session.cmd("echo %TEMP%\\#{file}"))[:data][0][:stdout].chomp
|
|
64
|
-
session.powershell <<-EOH
|
|
65
|
-
if(Test-Path #{to})
|
|
66
|
-
{
|
|
67
|
-
rm #{to}
|
|
68
|
-
}
|
|
69
|
-
EOH
|
|
70
|
-
Base64.encode64(IO.binread(from)).gsub("\n",'').chars.to_a.each_slice(8000-file_name.size) do |chunk|
|
|
71
|
-
out = session.cmd("echo #{chunk.join} >> \"#{file_name}\"")
|
|
72
|
-
end
|
|
73
|
-
session.powershell("mkdir $([System.IO.Path]::GetDirectoryName(\"#{to}\"))")
|
|
74
|
-
session.powershell <<-EOH
|
|
75
|
-
$base64_string = Get-Content \"#{file_name}\"
|
|
76
|
-
$bytes = [System.Convert]::FromBase64String($base64_string)
|
|
77
|
-
$new_file = [System.IO.Path]::GetFullPath(\"#{to}\")
|
|
78
|
-
[System.IO.File]::WriteAllBytes($new_file,$bytes)
|
|
79
|
-
EOH
|
|
71
|
+
winrmshell.upload(from, to)
|
|
80
72
|
end
|
|
81
73
|
|
|
82
74
|
def download(from, to=nil)
|
|
83
75
|
@logger.warn("Downloading: #{from} to #{to} not supported on Windows guests")
|
|
84
76
|
end
|
|
85
77
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
# Note: This is not part of the standard Vagrant communicator interface, but
|
|
89
|
-
# guest capabilities may need to use this.
|
|
90
|
-
def wql(query)
|
|
91
|
-
session.wql(query)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def set_winrmshell(winrmshell)
|
|
95
|
-
@session = winrmshell
|
|
78
|
+
def winrmshell=(winrmshell)
|
|
79
|
+
@winrmshell = winrmshell
|
|
96
80
|
end
|
|
97
81
|
|
|
98
|
-
def
|
|
99
|
-
@
|
|
82
|
+
def winrmshell
|
|
83
|
+
@winrmshell ||= @winrm_shell_factory.create_winrm_shell()
|
|
100
84
|
end
|
|
101
|
-
alias_method :winrmshell, :session
|
|
102
85
|
|
|
103
86
|
|
|
104
87
|
protected
|
|
105
88
|
|
|
106
|
-
def
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
89
|
+
def do_execute(command, shell, &block)
|
|
90
|
+
if shell.eql? :cmd
|
|
91
|
+
winrmshell.cmd(command, &block)[:exitcode]
|
|
92
|
+
else
|
|
93
|
+
command = VagrantWindows.load_script("command_alias.ps1") << "\r\n" << command << "\r\nexit $LASTEXITCODE"
|
|
94
|
+
winrmshell.powershell(command, &block)[:exitcode]
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def raise_execution_error(opts, exit_code)
|
|
99
|
+
# The error classes expect the translation key to be _key, but that makes for an ugly
|
|
100
|
+
# configuration parameter, so we set it here from `error_key`
|
|
101
|
+
msg = "Command execution failed with an exit code of #{exit_code}"
|
|
102
|
+
error_opts = opts.merge(:_key => opts[:error_key], :message => msg)
|
|
103
|
+
raise opts[:error_class], error_opts
|
|
116
104
|
end
|
|
117
105
|
|
|
118
106
|
end #WinRM class
|
|
119
107
|
end
|
|
120
|
-
end
|
|
108
|
+
end
|
|
@@ -1,43 +1,49 @@
|
|
|
1
1
|
require 'log4r'
|
|
2
2
|
require_relative '../errors'
|
|
3
|
+
require_relative '../windows_machine'
|
|
3
4
|
|
|
4
5
|
module VagrantWindows
|
|
5
6
|
module Communication
|
|
6
7
|
class WinRMFinder
|
|
7
8
|
|
|
8
9
|
attr_reader :logger
|
|
9
|
-
attr_reader :
|
|
10
|
+
attr_reader :windows_machine
|
|
10
11
|
|
|
11
|
-
def initialize(
|
|
12
|
-
@
|
|
12
|
+
def initialize(windows_machine)
|
|
13
|
+
@windows_machine = windows_machine
|
|
13
14
|
@logger = Log4r::Logger.new("vagrant_windows::communication::winrmfinder")
|
|
14
15
|
end
|
|
15
16
|
|
|
17
|
+
# Finds the address of the Windows machine.
|
|
18
|
+
# Raises a Vagrant::Errors::SSHNotReady if WinRM is not responding yet.
|
|
19
|
+
#
|
|
20
|
+
# @return [String] The IP of the Windows machine
|
|
16
21
|
def winrm_host_address
|
|
17
22
|
# Get the SSH info for the machine, raise an exception if the
|
|
18
|
-
# provider is saying that
|
|
19
|
-
ssh_info = @
|
|
20
|
-
raise
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
# provider is saying that the machine is not ready.
|
|
24
|
+
ssh_info = @windows_machine.ssh_info
|
|
25
|
+
raise VagrantWindows::Errors::WinRMNotReady if ssh_info.nil?
|
|
26
|
+
|
|
27
|
+
# if the configuration has a host value, that takes precedence
|
|
28
|
+
host = @windows_machine.winrm_config.host || ssh_info[:host]
|
|
29
|
+
@logger.info("WinRM host: #{host}")
|
|
30
|
+
host
|
|
23
31
|
end
|
|
24
32
|
|
|
33
|
+
# Finds the IP port of the Windows machine's WinRM service.
|
|
34
|
+
#
|
|
35
|
+
# @return [String] The port of the Windows machine's WinRM service
|
|
25
36
|
def winrm_host_port
|
|
26
|
-
expected_guest_port = @
|
|
37
|
+
expected_guest_port = @windows_machine.winrm_config.guest_port
|
|
27
38
|
@logger.debug("Searching for WinRM port: #{expected_guest_port.inspect}")
|
|
28
39
|
|
|
29
40
|
# Look for the forwarded port only by comparing the guest port
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return hostport if guestport == expected_guest_port
|
|
33
|
-
end
|
|
34
|
-
rescue NoMethodError => e
|
|
35
|
-
# VMWare provider doesn't support read_forwarded_ports
|
|
36
|
-
@logger.debug(e.message)
|
|
41
|
+
@windows_machine.read_forwarded_ports().each do |_, _, hostport, guestport|
|
|
42
|
+
return hostport if guestport == expected_guest_port
|
|
37
43
|
end
|
|
38
44
|
|
|
39
45
|
# We tried, give up and use the configured port as-is
|
|
40
|
-
@
|
|
46
|
+
@windows_machine.winrm_config.port
|
|
41
47
|
end
|
|
42
48
|
|
|
43
49
|
end
|
|
@@ -56,30 +56,48 @@ module VagrantWindows
|
|
|
56
56
|
def wql(query)
|
|
57
57
|
execute_wql(query)
|
|
58
58
|
end
|
|
59
|
+
|
|
60
|
+
def upload(from, to)
|
|
61
|
+
@logger.debug("Uploading: #{from} to #{to}")
|
|
62
|
+
file_name = (cmd("echo %TEMP%\\winrm-upload-#{rand()}"))[:data][0][:stdout].chomp
|
|
63
|
+
powershell <<-EOH
|
|
64
|
+
if(Test-Path #{to}) {
|
|
65
|
+
rm #{to}
|
|
66
|
+
}
|
|
67
|
+
EOH
|
|
68
|
+
Base64.encode64(IO.binread(from)).gsub("\n",'').chars.to_a.each_slice(8000-file_name.size) do |chunk|
|
|
69
|
+
out = cmd("echo #{chunk.join} >> \"#{file_name}\"")
|
|
70
|
+
end
|
|
71
|
+
powershell <<-EOH
|
|
72
|
+
mkdir $([System.IO.Path]::GetDirectoryName(\"#{to}\"))
|
|
73
|
+
$base64_string = Get-Content \"#{file_name}\"
|
|
74
|
+
$bytes = [System.Convert]::FromBase64String($base64_string)
|
|
75
|
+
$new_file = [System.IO.Path]::GetFullPath(\"#{to}\")
|
|
76
|
+
[System.IO.File]::WriteAllBytes($new_file,$bytes)
|
|
77
|
+
EOH
|
|
78
|
+
end
|
|
59
79
|
|
|
60
80
|
protected
|
|
61
81
|
|
|
62
82
|
def execute_shell(command, shell=:powershell, &block)
|
|
83
|
+
raise Errors::WinRMInvalidShell, :shell => shell unless shell == :cmd || shell == :powershell
|
|
84
|
+
begin
|
|
85
|
+
execute_shell_with_retry(command, shell, &block)
|
|
86
|
+
rescue => e
|
|
87
|
+
raise_winrm_exception(e, shell, command)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def execute_shell_with_retry(command, shell, &block)
|
|
63
92
|
retryable(:tries => @max_tries, :on => @@exceptions_to_retry_on, :sleep => 10) do
|
|
64
93
|
@logger.debug("#{shell} executing:\n#{command}")
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
block.call(:stderr, err) if block_given? && err
|
|
69
|
-
end
|
|
70
|
-
elsif shell.eql? :powershell
|
|
71
|
-
output = session.powershell(command) do |out, err|
|
|
72
|
-
block.call(:stdout, out) if block_given? && out
|
|
73
|
-
block.call(:stderr, err) if block_given? && err
|
|
74
|
-
end
|
|
75
|
-
else
|
|
76
|
-
raise Errors::WinRMInvalidShell, :shell => shell
|
|
94
|
+
output = session.send(shell, command) do |out, err|
|
|
95
|
+
block.call(:stdout, out) if block_given? && out
|
|
96
|
+
block.call(:stderr, err) if block_given? && err
|
|
77
97
|
end
|
|
78
98
|
@logger.debug("Exit status: #{output[:exitcode].inspect}")
|
|
79
99
|
return output
|
|
80
100
|
end
|
|
81
|
-
rescue => e
|
|
82
|
-
handle_winrm_exception(e, shell, command)
|
|
83
101
|
end
|
|
84
102
|
|
|
85
103
|
def execute_wql(query)
|
|
@@ -90,10 +108,10 @@ module VagrantWindows
|
|
|
90
108
|
return output
|
|
91
109
|
end
|
|
92
110
|
rescue => e
|
|
93
|
-
|
|
111
|
+
raise_winrm_exception(e, :wql, query)
|
|
94
112
|
end
|
|
95
113
|
|
|
96
|
-
def
|
|
114
|
+
def raise_winrm_exception(winrm_exception, shell, command)
|
|
97
115
|
if winrm_exception.message.include?("401") # return a more specific auth error for 401 errors
|
|
98
116
|
raise Errors::WinRMAuthorizationError,
|
|
99
117
|
:user => @username,
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require_relative 'winrmshell'
|
|
2
|
+
require_relative 'winrmfinder'
|
|
3
|
+
|
|
4
|
+
module VagrantWindows
|
|
5
|
+
module Communication
|
|
6
|
+
|
|
7
|
+
# Factory class for generating new WinRMShell instances
|
|
8
|
+
class WinRMShellFactory
|
|
9
|
+
|
|
10
|
+
# @param [WindowsMachine] The Windows machine instance
|
|
11
|
+
# @param [WinRMFinder] The WinRMFinder instance
|
|
12
|
+
def initialize(windows_machine, winrm_finder)
|
|
13
|
+
@windows_machine = windows_machine
|
|
14
|
+
@winrm_finder = winrm_finder
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Creates a new WinRMShell instance
|
|
18
|
+
#
|
|
19
|
+
# @return [WinRMShell]
|
|
20
|
+
def create_winrm_shell()
|
|
21
|
+
WinRMShell.new(
|
|
22
|
+
@winrm_finder.winrm_host_address(),
|
|
23
|
+
@windows_machine.winrm_config.username,
|
|
24
|
+
@windows_machine.winrm_config.password,
|
|
25
|
+
{
|
|
26
|
+
:port => @winrm_finder.winrm_host_port(),
|
|
27
|
+
:timeout_in_seconds => @windows_machine.winrm_config.timeout,
|
|
28
|
+
:max_tries => @windows_machine.winrm_config.max_tries
|
|
29
|
+
})
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end #WinShell class
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -27,7 +27,6 @@ module VagrantWindows
|
|
|
27
27
|
|
|
28
28
|
errors << "winrm.username cannot be nil." if machine.config.winrm.username.nil?
|
|
29
29
|
errors << "winrm.password cannot be nil." if machine.config.winrm.password.nil?
|
|
30
|
-
errors << "winrm.host cannot be nil." if machine.config.winrm.host.nil?
|
|
31
30
|
errors << "winrm.port cannot be nil." if machine.config.winrm.port.nil?
|
|
32
31
|
errors << "winrm.guest_port cannot be nil." if machine.config.winrm.guest_port.nil?
|
|
33
32
|
errors << "winrm.max_tries cannot be nil." if machine.config.winrm.max_tries.nil?
|
|
@@ -39,7 +38,7 @@ module VagrantWindows
|
|
|
39
38
|
def finalize!
|
|
40
39
|
@username = "vagrant" if @username == UNSET_VALUE
|
|
41
40
|
@password = "vagrant" if @password == UNSET_VALUE
|
|
42
|
-
@host =
|
|
41
|
+
@host = nil if @host == UNSET_VALUE
|
|
43
42
|
@port = 5985 if @port == UNSET_VALUE
|
|
44
43
|
@guest_port = 5985 if @guest_port == UNSET_VALUE
|
|
45
44
|
@max_tries = 20 if @max_tries == UNSET_VALUE
|
|
@@ -7,8 +7,8 @@ module VagrantWindows
|
|
|
7
7
|
error_namespace("vagrant_windows.errors")
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
class
|
|
11
|
-
error_key(:
|
|
10
|
+
class WinRMNotReady < VagrantWindowsError
|
|
11
|
+
error_key(:winrm_not_ready)
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
class WinRMInvalidShell < VagrantWindowsError
|
|
@@ -2,6 +2,8 @@ require 'log4r'
|
|
|
2
2
|
require_relative '../../communication/guestnetwork'
|
|
3
3
|
require_relative '../../communication/winrmshell'
|
|
4
4
|
require_relative '../../errors'
|
|
5
|
+
require_relative '../../helper'
|
|
6
|
+
require_relative '../../windows_machine'
|
|
5
7
|
|
|
6
8
|
module VagrantWindows
|
|
7
9
|
module Guest
|
|
@@ -13,47 +15,49 @@ module VagrantWindows
|
|
|
13
15
|
def self.configure_networks(machine, networks)
|
|
14
16
|
@@logger.debug("networks: #{networks.inspect}")
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
18
|
+
windows_machine = VagrantWindows::WindowsMachine.new(machine)
|
|
19
|
+
guest_network = VagrantWindows::Communication::GuestNetwork.new(windows_machine.winrmshell)
|
|
20
|
+
if windows_machine.is_vmware?()
|
|
21
|
+
@@logger.warn('Configuring secondary network adapters through VMware is not yet supported.')
|
|
22
|
+
@@logger.warn('You will need to manually configure the network adapter.')
|
|
23
|
+
else
|
|
24
|
+
vm_interface_map = create_vm_interface_map(windows_machine, guest_network)
|
|
25
|
+
networks.each do |network|
|
|
26
|
+
interface = vm_interface_map[network[:interface]+1]
|
|
27
|
+
if interface.nil?
|
|
28
|
+
@@logger.warn("Could not find interface for network #{network.inspect}")
|
|
29
|
+
next
|
|
30
|
+
end
|
|
31
|
+
network_type = network[:type].to_sym
|
|
32
|
+
if network_type == :static
|
|
33
|
+
guest_network.configure_static_interface(
|
|
34
|
+
interface[:index],
|
|
35
|
+
interface[:net_connection_id],
|
|
36
|
+
network[:ip],
|
|
37
|
+
network[:netmask])
|
|
38
|
+
elsif network_type == :dhcp
|
|
39
|
+
guest_network.configure_dhcp_interface(
|
|
40
|
+
interface[:index],
|
|
41
|
+
interface[:net_connection_id])
|
|
42
|
+
else
|
|
43
|
+
raise WindowsError, "#{network_type} network type is not supported, try static or dhcp"
|
|
44
|
+
end
|
|
41
45
|
end
|
|
42
46
|
end
|
|
43
|
-
guest_network.set_all_networks_to_work() if
|
|
47
|
+
guest_network.set_all_networks_to_work() if windows_machine.windows_config.set_work_network
|
|
44
48
|
end
|
|
45
49
|
|
|
46
50
|
#{1=>{:name=>"Local Area Connection", :mac_address=>"0800275FAC5B", :interface_index=>"11", :index=>"7"}}
|
|
47
|
-
def self.create_vm_interface_map(
|
|
51
|
+
def self.create_vm_interface_map(windows_machine, guest_network)
|
|
48
52
|
vm_interface_map = {}
|
|
49
|
-
driver_mac_address =
|
|
53
|
+
driver_mac_address = windows_machine.read_mac_addresses.invert
|
|
50
54
|
@@logger.debug("mac addresses: #{driver_mac_address.inspect}")
|
|
51
55
|
guest_network.network_adapters().each do |nic|
|
|
52
56
|
@@logger.debug("nic: #{nic.inspect}")
|
|
53
57
|
naked_mac = nic[:mac_address].gsub(':','')
|
|
54
58
|
if driver_mac_address[naked_mac]
|
|
55
59
|
vm_interface_map[driver_mac_address[naked_mac]] = {
|
|
56
|
-
:
|
|
60
|
+
:net_connection_id => nic[:net_connection_id],
|
|
57
61
|
:mac_address => naked_mac,
|
|
58
62
|
:interface_index => nic[:interface_index],
|
|
59
63
|
:index => nic[:index] }
|
|
@@ -3,6 +3,10 @@ module VagrantWindows
|
|
|
3
3
|
module Cap
|
|
4
4
|
class Halt
|
|
5
5
|
def self.halt(machine)
|
|
6
|
+
# Fix defect 129, if there's an existing scheduled reboot cancel it so shutdown succeeds
|
|
7
|
+
machine.communicate.execute("shutdown -a", :error_check => false)
|
|
8
|
+
|
|
9
|
+
# Force shutdown the machine now
|
|
6
10
|
machine.communicate.execute("shutdown /s /t 1 /c \"Vagrant Halt\" /f /d p:4:1")
|
|
7
11
|
|
|
8
12
|
# Wait until the VM's state is actually powered off. If this doesn't
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require_relative '../../helper'
|
|
2
|
+
|
|
3
|
+
module VagrantWindows
|
|
4
|
+
module Guest
|
|
5
|
+
module Cap
|
|
6
|
+
class MountSharedFolder
|
|
7
|
+
|
|
8
|
+
def self.mount_virtualbox_shared_folder(machine, name, guestpath, options)
|
|
9
|
+
mount_shared_folder(machine, name, guestpath, "\\\\vboxsrv\\")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.mount_vmware_shared_folder(machine, name, guestpath, options)
|
|
13
|
+
mount_shared_folder(machine, name, guestpath, "\\\\vmware-host\\Shared Folders\\")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
protected
|
|
17
|
+
|
|
18
|
+
def self.mount_shared_folder(machine, name, guestpath, vm_provider_unc_base)
|
|
19
|
+
share_name = VagrantWindows::Helper.win_friendly_share_id(name)
|
|
20
|
+
options = {
|
|
21
|
+
:mount_point => guestpath,
|
|
22
|
+
:share_name => share_name,
|
|
23
|
+
:vm_provider_unc_path => vm_provider_unc_base + share_name}
|
|
24
|
+
mount_script = VagrantWindows.load_script_template("mount_volume.ps1", :options => options)
|
|
25
|
+
machine.communicate.execute(mount_script, {:shell => :powershell})
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
require "vagrant"
|
|
2
|
+
require "vagrant-windows/helper"
|
|
2
3
|
require "vagrant-windows/guest/cap/change_host_name"
|
|
3
4
|
require "vagrant-windows/guest/cap/configure_networks"
|
|
4
5
|
require "vagrant-windows/guest/cap/halt"
|
|
5
|
-
require "vagrant-windows/guest/cap/
|
|
6
|
-
require "vagrant-windows/guest/cap/mount_vmware_shared_folder"
|
|
6
|
+
require "vagrant-windows/guest/cap/mount_shared_folder"
|
|
7
7
|
|
|
8
8
|
module VagrantWindows
|
|
9
9
|
module Guest
|
|
10
10
|
class Windows < Vagrant.plugin("2", :guest)
|
|
11
11
|
|
|
12
|
-
# Vagrant 1.1.x
|
|
12
|
+
# Vagrant 1.1.x compatibility methods
|
|
13
13
|
# Implement the 1.1.x methods and call through to the new 1.2.x capabilities
|
|
14
14
|
|
|
15
|
+
attr_reader :windows_machine
|
|
15
16
|
attr_reader :machine
|
|
16
17
|
|
|
17
18
|
def initialize(machine = nil)
|
|
18
19
|
super(machine) unless machine == nil
|
|
19
20
|
@machine = machine
|
|
21
|
+
@windows_machine = ::VagrantWindows::WindowsMachine.new(machine)
|
|
20
22
|
end
|
|
21
23
|
|
|
22
24
|
def change_host_name(name)
|
|
@@ -31,14 +33,14 @@ module VagrantWindows
|
|
|
31
33
|
VagrantWindows::Guest::Cap::Halt.halt(@machine)
|
|
32
34
|
end
|
|
33
35
|
|
|
34
|
-
def
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
VagrantWindows::Guest::Cap::MountVMwareBoxSharedFolder.mount_vmware_shared_folder(
|
|
36
|
+
def mount_shared_folder(name, guestpath, options)
|
|
37
|
+
if @windows_machine.is_vmware?() then
|
|
38
|
+
VagrantWindows::Guest::Cap::MountSharedFolder.mount_vmware_shared_folder(
|
|
39
|
+
@machine, name, guestpath, options)
|
|
40
|
+
else
|
|
41
|
+
VagrantWindows::Guest::Cap::MountSharedFolder.mount_virtualbox_shared_folder(
|
|
41
42
|
@machine, name, guestpath, options)
|
|
43
|
+
end
|
|
42
44
|
end
|
|
43
45
|
|
|
44
46
|
def configure_networks(networks)
|
|
@@ -46,7 +48,7 @@ module VagrantWindows
|
|
|
46
48
|
end
|
|
47
49
|
|
|
48
50
|
|
|
49
|
-
# Vagrant 1.2.x
|
|
51
|
+
# Vagrant 1.2.x compatibility methods
|
|
50
52
|
|
|
51
53
|
def detect?(machine)
|
|
52
54
|
|
|
@@ -2,6 +2,12 @@ module VagrantWindows
|
|
|
2
2
|
module Helper
|
|
3
3
|
extend self
|
|
4
4
|
|
|
5
|
+
@@logger = Log4r::Logger.new("vagrant_windows::helper")
|
|
6
|
+
|
|
7
|
+
# Makes a path Windows guest friendly.
|
|
8
|
+
# Turns '/vagrant' into 'c:\vagrant'
|
|
9
|
+
#
|
|
10
|
+
# @return [String]
|
|
5
11
|
def win_friendly_path(path)
|
|
6
12
|
if path
|
|
7
13
|
new_path = path.gsub('/', '\\')
|
|
@@ -10,10 +16,25 @@ module VagrantWindows
|
|
|
10
16
|
new_path
|
|
11
17
|
end
|
|
12
18
|
|
|
13
|
-
#
|
|
19
|
+
# Makes Vagrant share names Windows guest friendly.
|
|
20
|
+
# Turns '/vagrant' into 'vagrant' or turns ''/a/b/c/d/e' into 'a_b_c_d_e'
|
|
21
|
+
#
|
|
22
|
+
# @return [String]
|
|
14
23
|
def win_friendly_share_id(shared_folder_name)
|
|
15
24
|
return shared_folder_name.gsub(/[\/\/]/,'_').sub(/^_/, '')
|
|
16
25
|
end
|
|
17
26
|
|
|
27
|
+
# Check to see if the guest is rebooting, if its rebooting then wait until its ready
|
|
28
|
+
#
|
|
29
|
+
# @param [WindowsMachine] The windows machine instance
|
|
30
|
+
# @param [Int] The time in seconds to wait between checks
|
|
31
|
+
def wait_if_rebooting(windows_machine, wait_in_seconds=10)
|
|
32
|
+
@@logger.info('Checking guest reboot status')
|
|
33
|
+
while windows_machine.is_rebooting?
|
|
34
|
+
@@logger.debug('Guest is rebooting, waiting 10 seconds...')
|
|
35
|
+
sleep(wait_in_seconds)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
18
39
|
end
|
|
19
40
|
end
|