vagrant-windows 1.6.0 → 1.7.0.pre.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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -1
  3. data/CHANGELOG.md +7 -1
  4. data/Gemfile +5 -1
  5. data/README.md +3 -1
  6. data/lib/vagrant-windows/communication/command_filters/cat.rb +27 -0
  7. data/lib/vagrant-windows/communication/command_filters/chmod.rb +21 -0
  8. data/lib/vagrant-windows/communication/command_filters/chown.rb +21 -0
  9. data/lib/vagrant-windows/communication/command_filters/rm.rb +28 -0
  10. data/lib/vagrant-windows/communication/command_filters/test.rb +37 -0
  11. data/lib/vagrant-windows/communication/command_filters/uname.rb +36 -0
  12. data/lib/vagrant-windows/communication/command_filters/which.rb +26 -0
  13. data/lib/vagrant-windows/communication/linux_command_filter.rb +44 -0
  14. data/lib/vagrant-windows/communication/winrmcommunicator.rb +19 -12
  15. data/lib/vagrant-windows/communication/winrmfilemanager.rb +166 -0
  16. data/lib/vagrant-windows/communication/winrmshell.rb +4 -23
  17. data/lib/vagrant-windows/errors.rb +5 -1
  18. data/lib/vagrant-windows/monkey_patches/plugins/provisioners/chef/provisioner/chef_client.rb +2 -5
  19. data/lib/vagrant-windows/monkey_patches/plugins/provisioners/chef/provisioner/chef_solo.rb +2 -5
  20. data/lib/vagrant-windows/monkey_patches/plugins/provisioners/shell/provisioner.rb +13 -6
  21. data/lib/vagrant-windows/provisioners/chef_command_builder.rb +7 -53
  22. data/lib/vagrant-windows/scripts/elevated_shell.ps1.erb +95 -0
  23. data/lib/vagrant-windows/version.rb +1 -1
  24. data/locales/en.yml +7 -0
  25. data/spec/vagrant-windows/chef_command_builder_spec.rb +7 -53
  26. data/spec/vagrant-windows/guestnetwork_spec.rb +3 -3
  27. data/spec/vagrant-windows/linux_command_filter_spec.rb +73 -0
  28. data/spec/vagrant-windows/winrmcommunicator_spec.rb +55 -6
  29. data/spec/vagrant-windows/winrmshell_spec.rb +3 -3
  30. metadata +16 -8
  31. data/lib/vagrant-windows/scripts/cheftask.ps1.erb +0 -48
  32. data/lib/vagrant-windows/scripts/cheftask.xml.erb +0 -45
  33. data/lib/vagrant-windows/scripts/cheftaskrun.ps1.erb +0 -18
  34. data/lib/vagrant-windows/scripts/command_alias.ps1 +0 -36
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6e89e485b8fae09a9d784792b184ebbc61d70185
4
- data.tar.gz: a36e78c2c59df8921a7ad3db46ac7713d02a04d7
3
+ metadata.gz: 9e0d8f67d7fd5775bc1dfffb01aee0f766c5c512
4
+ data.tar.gz: fd24bde9a3b09754acb450f2995a61c0292a7294
5
5
  SHA512:
6
- metadata.gz: 035e50bbe58c5e2512624982e1a2797f36530ce8855c67e45dbd5ab3aea8d15390aab866b870c660a870799061cdcec33f006f610928812ee4cb747685a5901d
7
- data.tar.gz: a23744a7c72a969c0ea40a935b1a5deb8c85bafc0a4815f4729d232c7f74a7a12ea0283156b88499740b175d6085e702d69b80a66ad129e873e72c059a868c80
6
+ metadata.gz: 081a4d22f0f528b6672009678de4c7558c24059036a62c5d8e595073de8cc4566c38f72c78bacd3a67d5a9da6b2a2b8d96a356dc26b391adf8bb59c11a75ec57
7
+ data.tar.gz: c11a66f853413fc9ca9970ce767c1a71ddd3c0193766a9cf7980b9aeb5af67dfff414720e1ea3e4116b0072925353bd780d300bbe94ab75f59372b23319f1d8e
data/.travis.yml CHANGED
@@ -1,5 +1,4 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.3
4
3
  - 2.0.0
5
4
  - 2.1.0
data/CHANGELOG.md CHANGED
@@ -76,4 +76,10 @@
76
76
 
77
77
  1.6.0
78
78
  - Added chef-client provisioner support and extracted shared code from chef-solo provisioner
79
- - WinRM communicator download support
79
+ - WinRM communicator download support
80
+
81
+ 1.7.0
82
+ - Added recursive directory upload on communicator, similar to core Vagrant SCP functionality.
83
+ - Redesigned elevated command execution in Chef to make it reusable
84
+ - Shell provisioner now runs elevated by default unless privileged is false
85
+ - Removed *nix command alias PS script and created extensible linux command filter system
data/Gemfile CHANGED
@@ -7,6 +7,10 @@ group :development do
7
7
  # We depend on Vagrant for development, but we don't add it as a
8
8
  # gem dependency because we expect to be installed within the
9
9
  # Vagrant environment itself using `vagrant plugin`.
10
- gem "vagrant", :git => "git://github.com/mitchellh/vagrant.git", :tag => 'v1.4.0'
10
+ gem "vagrant", :git => "git://github.com/mitchellh/vagrant.git", :tag => 'v1.5.2'
11
11
  gem "mocha", :require => false
12
12
  end
13
+
14
+ group :plugins do
15
+ gem "vagrant-windows", path: '.'
16
+ end
data/README.md CHANGED
@@ -13,7 +13,9 @@ This [Vagrant](http://www.vagrantup.com/) plugin allows you to standup Windows g
13
13
 
14
14
  ## Installation
15
15
 
16
- - For Vagrant 1.1 and above execute `vagrant plugin install vagrant-windows`.
16
+ Vagrant 1.6 will natively support Windows guests, this plugin should not be used with Vagrant 1.6 or later.
17
+
18
+ - For Vagrant 1.1 -> 1.5 execute `vagrant plugin install vagrant-windows`.
17
19
  - For Vagrant 1.0 execute `vagrant plugin install vagrant-windows --plugin-version 0.1.2`.
18
20
 
19
21
  ## Creating a Base Box
@@ -0,0 +1,27 @@
1
+ module VagrantWindows
2
+ module Communication
3
+ module CommandFilters
4
+
5
+ # Handles the special case of determining the guest OS using cat
6
+ class Cat
7
+
8
+ def filter(command)
9
+ # cat /etc/release | grep -i OmniOS
10
+ # cat /etc/redhat-release
11
+ # cat /etc/issue | grep 'Core Linux'
12
+ # cat /etc/release | grep -i SmartOS
13
+ ''
14
+ end
15
+
16
+ def accept?(command)
17
+ # cat works in PowerShell, however we don't want to run Guest
18
+ # OS detection as this will fail on Windows because the lack of the
19
+ # grep command
20
+ command.start_with?('cat /etc/')
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ module VagrantWindows
2
+ module Communication
3
+ module CommandFilters
4
+
5
+ # Converts a *nix 'chmod' command to a PowerShell equivalent
6
+ class Chmod
7
+
8
+ def filter(command)
9
+ # Not support on Windows, the communicator will skip this command
10
+ ''
11
+ end
12
+
13
+ def accept?(command)
14
+ command.start_with?('chmod ')
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module VagrantWindows
2
+ module Communication
3
+ module CommandFilters
4
+
5
+ # Converts a *nix 'chown' command to a PowerShell equivalent
6
+ class Chown
7
+
8
+ def filter(command)
9
+ # Not support on Windows, the communicator will skip this command
10
+ ''
11
+ end
12
+
13
+ def accept?(command)
14
+ command.start_with?('chown ')
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,28 @@
1
+ module VagrantWindows
2
+ module Communication
3
+ module CommandFilters
4
+
5
+ # Converts a *nix 'rm' command to a PowerShell equivalent
6
+ class Rm
7
+
8
+ def filter(command)
9
+ # rm -Rf /some/dir
10
+ # rm /some/dir
11
+ cmd_parts = command.strip.split(/\s+/)
12
+ dir = cmd_parts[1]
13
+ if dir == '-Rf'
14
+ dir = cmd_parts[2]
15
+ return "rm '#{dir}' -recurse -force"
16
+ end
17
+ return "rm '#{dir}' -force"
18
+ end
19
+
20
+ def accept?(command)
21
+ command.start_with?('rm ')
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,37 @@
1
+ module VagrantWindows
2
+ module Communication
3
+ module CommandFilters
4
+
5
+ # Converts a *nix 'test' command to a PowerShell equivalent
6
+ class Test
7
+
8
+ def filter(command)
9
+ # test -d /tmp/dir
10
+ # test -f /tmp/afile
11
+ # test -L /somelink
12
+ # test -x /tmp/some.exe
13
+
14
+ cmd_parts = command.strip.split(/\s+/)
15
+ if cmd_parts[1] == '-d'
16
+ # ensure it exists and is a directory
17
+ return "if ((Test-Path '#{cmd_parts[2]}') -and (get-item '#{cmd_parts[2]}').PSIsContainer) { exit 0 } exit 1"
18
+ elsif cmd_parts[1] == '-f' || cmd_parts[1] == '-x'
19
+ # ensure it exists and is a file
20
+ return "if ((Test-Path '#{cmd_parts[2]}') -and (!(get-item '#{cmd_parts[2]}').PSIsContainer)) { exit 0 } exit 1"
21
+ end
22
+
23
+ # otherwise, just check for existence
24
+ return "if (Test-Path '#{cmd_parts[2]}') { exit 0 } exit 1"
25
+ end
26
+
27
+ # if (Test-Path 'c:\windows' && (get-item 'c:\windows').PSIsContainer) { Write-Host 0 } Write-Host 1
28
+
29
+ def accept?(command)
30
+ command.start_with?('test ')
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,36 @@
1
+ # cat /etc/release | grep -i OmniOS
2
+ # cat /etc/redhat-release
3
+ # cat /etc/issue | grep 'Core Linux'
4
+ # cat /etc/release | grep -i SmartOS
5
+
6
+ module VagrantWindows
7
+ module Communication
8
+ module CommandFilters
9
+
10
+ # Converts a *nix 'uname' command to a PowerShell equivalent
11
+ class Uname
12
+
13
+ def filter(command)
14
+ # uname -s | grep 'Darwin'
15
+ # uname -s | grep VMkernel
16
+ # uname -s | grep 'FreeBSD'
17
+ # uname -s | grep 'Linux'
18
+ # uname -s | grep NetBSD
19
+ # uname -s | grep 'OpenBSD'
20
+ # uname -sr | grep SunOS | grep -v 5.11
21
+ # uname -sr | grep 'SunOS 5.11'
22
+
23
+ # uname is used to detect the guest type in Vagrant, so don't bother running
24
+ # to speed up OS detection
25
+ ''
26
+ end
27
+
28
+ def accept?(command)
29
+ command.start_with?('uname ')
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,26 @@
1
+ module VagrantWindows
2
+ module Communication
3
+ module CommandFilters
4
+
5
+ # Converts a *nix 'which' command to a PowerShell equivalent
6
+ class Which
7
+
8
+ def filter(command)
9
+ executable = command.strip.split(/\s+/)[1]
10
+ return <<-EOH
11
+ $command = [Array](Get-Command #{executable} -errorAction SilentlyContinue)
12
+ if ($null -eq $command) { exit 1 }
13
+ write-host $command[0].Definition
14
+ exit 0
15
+ EOH
16
+ end
17
+
18
+ def accept?(command)
19
+ command.start_with?('which ')
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,44 @@
1
+ module VagrantWindows
2
+ module Communication
3
+
4
+ # Handles loading all available Linix command filters and applying them
5
+ # to specified command
6
+ class LinuxCommandFilter
7
+
8
+ # Filter the given Vagrant command to ensure compatibility with Windows
9
+ #
10
+ # @param [String] The Vagrant shell command
11
+ # @returns [String] Windows runnable command or empty string
12
+ def filter(command)
13
+ win_friendly_cmd = command
14
+ command_filters.each do |cmd_filter|
15
+ win_friendly_cmd = cmd_filter.filter(win_friendly_cmd) if cmd_filter.accept?(win_friendly_cmd)
16
+ end
17
+ win_friendly_cmd
18
+ end
19
+
20
+
21
+ # All the available Linux command filters
22
+ #
23
+ # @returns [Array] All Linux command filter instances
24
+ def command_filters
25
+ @command_filters ||= create_command_filters()
26
+ end
27
+
28
+ # Creates all the available Linux command filters
29
+ #
30
+ # @returns [Array] All Linux command filter instances
31
+ def create_command_filters
32
+ filters = []
33
+ Dir[File.join(File.dirname(__FILE__), '/command_filters/*.rb')].each do |file|
34
+ require file
35
+ clazz = File.basename(file, '.*').capitalize
36
+ filters << Module.const_get("VagrantWindows::Communication::CommandFilters::#{clazz}").new
37
+ end
38
+ filters
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+ end
@@ -2,7 +2,9 @@ require 'timeout'
2
2
  require 'log4r'
3
3
  require_relative 'winrmshell_factory'
4
4
  require_relative 'winrmshell'
5
+ require_relative 'winrmfilemanager'
5
6
  require_relative 'winrmfinder'
7
+ require_relative 'linux_command_filter'
6
8
  require_relative '../errors'
7
9
  require_relative '../windows_machine'
8
10
 
@@ -18,7 +20,7 @@ module VagrantWindows
18
20
  def initialize(machine)
19
21
  @windows_machine = VagrantWindows::WindowsMachine.new(machine)
20
22
  @winrm_shell_factory = WinRMShellFactory.new(@windows_machine, WinRMFinder.new(@windows_machine))
21
-
23
+ @linux_cmd_filter = LinuxCommandFilter.new()
22
24
  @logger = Log4r::Logger.new("vagrant_windows::communication::winrmcommunicator")
23
25
  @logger.debug("initializing WinRMCommunicator")
24
26
  end
@@ -45,14 +47,20 @@ module VagrantWindows
45
47
  end
46
48
 
47
49
  def execute(command, opts={}, &block)
50
+ # If this is a *nix command with no Windows equivilant, don't run it
51
+ win_friendly_cmd = @linux_cmd_filter.filter(command)
52
+ if (win_friendly_cmd.empty?)
53
+ return { :exitcode => 0, :stderr => '', :stdout => '' }
54
+ end
55
+
48
56
  opts = {
49
57
  :error_check => true,
50
58
  :error_class => VagrantWindows::Errors::WinRMExecutionError,
51
59
  :error_key => :winrm_execution_error,
52
- :command => command,
60
+ :command => win_friendly_cmd,
53
61
  :shell => :powershell
54
62
  }.merge(opts || {})
55
- exit_status = do_execute(command, opts[:shell], &block)
63
+ exit_status = do_execute(win_friendly_cmd, opts[:shell], &block)
56
64
  if opts[:error_check] && exit_status != 0
57
65
  raise_execution_error(opts, exit_status)
58
66
  end
@@ -61,22 +69,21 @@ module VagrantWindows
61
69
  alias_method :sudo, :execute
62
70
 
63
71
  def test(command, opts=nil)
64
- @logger.debug("Testing: #{command}")
65
-
66
- # HACK: to speed up Vagrant 1.2 OS detection, skip checking for *nix OS
67
- return false unless (command =~ /^uname|^cat \/etc|^cat \/proc|grep 'Fedora/).nil?
72
+ # If this is a *nix command with no Windows equivilant, don't run it
73
+ win_friendly_cmd = @linux_cmd_filter.filter(command)
74
+ if (win_friendly_cmd.empty?)
75
+ return false
76
+ end
68
77
 
69
78
  opts = { :error_check => false }.merge(opts || {})
70
- execute(command, opts) == 0
79
+ execute(win_friendly_cmd, opts) == 0
71
80
  end
72
81
 
73
82
  def upload(from, to)
74
- @logger.debug("Uploading: #{from} to #{to}")
75
83
  winrmshell.upload(from, to)
76
84
  end
77
85
 
78
86
  def download(from, to)
79
- @logger.debug("Downloading: #{from} to #{to}")
80
87
  winrmshell.download(from, to)
81
88
  end
82
89
 
@@ -87,7 +94,7 @@ module VagrantWindows
87
94
  def winrmshell
88
95
  @winrmshell ||= @winrm_shell_factory.create_winrm_shell()
89
96
  end
90
-
97
+
91
98
 
92
99
  protected
93
100
 
@@ -95,7 +102,7 @@ module VagrantWindows
95
102
  if shell.eql? :cmd
96
103
  winrmshell.cmd(command, &block)[:exitcode]
97
104
  else
98
- command = VagrantWindows.load_script("command_alias.ps1") << "\r\n" << command << "\r\nexit $LASTEXITCODE"
105
+ command << "\r\nexit $LASTEXITCODE"
99
106
  winrmshell.powershell(command, &block)[:exitcode]
100
107
  end
101
108
  end
@@ -0,0 +1,166 @@
1
+ require 'log4r'
2
+ require 'winrm'
3
+ require_relative 'winrmshell'
4
+ require_relative '../errors'
5
+
6
+ module VagrantWindows
7
+ module Communication
8
+
9
+ # Manages the file system on the remote guest allowing for file tranfer
10
+ # between the guest and host.
11
+ class WinRMFileManager
12
+
13
+ def initialize(winrm_shell)
14
+ @logger = Log4r::Logger.new("vagrant_windows::communication::winrmfilemanager")
15
+ @winrm_shell = winrm_shell
16
+ end
17
+
18
+ # Uploads the given file or directory from the host to the guest (recursively).
19
+ #
20
+ # @param [String] The source file or directory path on the host
21
+ # @param [String] The destination file or directory path on the host
22
+ def upload(host_src_file_path, guest_dest_file_path)
23
+ @logger.debug("Upload: #{host_src_file_path} -> #{guest_dest_file_path}")
24
+ if File.directory?(host_src_file_path)
25
+ upload_directory(host_src_file_path, guest_dest_file_path)
26
+ else
27
+ upload_file(host_src_file_path, guest_dest_file_path)
28
+ end
29
+ end
30
+
31
+ # Downloads the given file from the guest to the host.
32
+ # NOTE: This currently only supports single file download
33
+ #
34
+ # @param [String] The source file path on the guest
35
+ # @param [String] The destination file path on the host
36
+ def download(guest_src_file_path, host_dest_file_path)
37
+ @logger.debug("#{guest_src_file_path} -> #{host_dest_file_path}")
38
+ output = @winrm_shell.powershell("[System.convert]::ToBase64String([System.IO.File]::ReadAllBytes(\"#{guest_src_file_path}\"))")
39
+ contents = output[:data].map!{|line| line[:stdout]}.join.gsub("\\n\\r", '')
40
+ out = Base64.decode64(contents)
41
+ IO.binwrite(host_dest_file_path, out)
42
+ end
43
+
44
+
45
+ private
46
+
47
+ # Recursively uploads the given directory from the host to the guest
48
+ #
49
+ # @param [String] The source file or directory path on the host
50
+ # @param [String] The destination file or directory path on the host
51
+ def upload_directory(host_src_file_path, guest_dest_file_path)
52
+ glob_patt = File.join(host_src_file_path, '**/*')
53
+ Dir.glob(glob_patt).select { |f| !File.directory?(f) }.each do |host_file_path|
54
+ guest_file_path = guest_file_path(host_src_file_path, guest_dest_file_path, host_file_path)
55
+ upload_file(host_file_path, guest_file_path)
56
+ end
57
+ end
58
+
59
+ # Uploads the given file, but only if the target file doesn't exist
60
+ # or its MD5 checksum doens't match the host's source checksum.
61
+ #
62
+ # @param [String] The source file path on the host
63
+ # @param [String] The destination file path on the guest
64
+ def upload_file(host_src_file_path, guest_dest_file_path)
65
+ if should_upload_file?(host_src_file_path, guest_dest_file_path)
66
+ tmp_file_path = upload_to_temp_file(host_src_file_path)
67
+ decode_temp_file(tmp_file_path, guest_dest_file_path)
68
+ else
69
+ @logger.debug("Up to date: #{guest_dest_file_path}")
70
+ end
71
+ end
72
+
73
+ # Uploads the given file to a new temp file on the guest
74
+ #
75
+ # @param [String] The source file path on the host
76
+ # @return [String] The temp file path on the guest
77
+ def upload_to_temp_file(host_src_file_path)
78
+ tmp_file_path = File.join(guest_temp_dir, "winrm-upload-#{rand()}")
79
+ @logger.debug("Uploading '#{host_src_file_path}' to temp file '#{tmp_file_path}'")
80
+ base64_host_file = Base64.encode64(IO.binread(host_src_file_path)).gsub("\n",'')
81
+ base64_host_file.chars.to_a.each_slice(8000-tmp_file_path.size) do |chunk|
82
+ out = @winrm_shell.cmd("echo #{chunk.join} >> \"#{tmp_file_path}\"")
83
+ raise_upload_error_if_failed(out, host_src_file_path, tmp_file_path)
84
+ end
85
+ tmp_file_path
86
+ end
87
+
88
+ # Moves and decodes the given file temp file on the guest to its
89
+ # permanent location
90
+ #
91
+ # @param [String] The source base64 encoded temp file path on the guest
92
+ # @param [String] The destination file path on the guest
93
+ def decode_temp_file(guest_tmp_file_path, guest_dest_file_path)
94
+ @logger.debug("Decoding temp file '#{guest_tmp_file_path}' to '#{guest_dest_file_path}'")
95
+ out = @winrm_shell.powershell <<-EOH
96
+ $tmp_file_path = [System.IO.Path]::GetFullPath('#{guest_tmp_file_path}')
97
+ $dest_file_path = [System.IO.Path]::GetFullPath('#{guest_dest_file_path}')
98
+
99
+ if (Test-Path $dest_file_path) {
100
+ rm $dest_file_path
101
+ }
102
+ else {
103
+ $dest_dir = ([System.IO.Path]::GetDirectoryName($dest_file_path))
104
+ New-Item -ItemType directory -Force -Path $dest_dir
105
+ }
106
+
107
+ $base64_string = Get-Content $tmp_file_path
108
+ $bytes = [System.Convert]::FromBase64String($base64_string)
109
+ [System.IO.File]::WriteAllBytes($dest_file_path, $bytes)
110
+ EOH
111
+ raise_upload_error_if_failed(out, guest_tmp_file_path, guest_dest_file_path)
112
+ end
113
+
114
+ # Checks to see if the target file on the guest is missing or out of date.
115
+ #
116
+ # @param [String] The source file path on the host
117
+ # @param [String] The destination file path on the guest
118
+ # @return [Boolean] True if the file is missing or out of date
119
+ def should_upload_file?(host_src_file_path, guest_dest_file_path)
120
+ local_md5 = Digest::MD5.file(host_src_file_path).hexdigest
121
+ cmd = <<-EOH
122
+ $dest_file_path = [System.IO.Path]::GetFullPath('#{guest_dest_file_path}')
123
+
124
+ if (Test-Path $dest_file_path) {
125
+ $crypto_provider = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
126
+ try {
127
+ $file = [System.IO.File]::Open($dest_file_path, [System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)
128
+ $guest_md5 = ([System.BitConverter]::ToString($crypto_provider.ComputeHash($file))).Replace("-","").ToLower()
129
+ }
130
+ finally {
131
+ $file.Dispose()
132
+ }
133
+ if ($guest_md5 -eq '#{local_md5}') {
134
+ exit 0
135
+ }
136
+ }
137
+ exit 1
138
+ EOH
139
+ @winrm_shell.powershell(cmd)[:exitcode] == 1
140
+ end
141
+
142
+ # Creates a guest file path equivalent from a host file path
143
+ #
144
+ # @param [String] The base host directory we're going to copy from
145
+ # @param [String] The base guest directory we're going to copy to
146
+ # @param [String] A full path to a file on the host underneath host_base_dir
147
+ # @return [String] The guest file path equivalent
148
+ def guest_file_path(host_base_dir, guest_base_dir, host_file_path)
149
+ rel_path = File.dirname(host_file_path[host_base_dir.length, host_file_path.length])
150
+ File.join(guest_base_dir, rel_path, File.basename(host_file_path))
151
+ end
152
+
153
+ def guest_temp_dir
154
+ @guest_temp ||= (@winrm_shell.cmd('echo %TEMP%'))[:data][0][:stdout].chomp
155
+ end
156
+
157
+ def raise_upload_error_if_failed(out, from, to)
158
+ raise Errors::WinRMFileTransferError,
159
+ :from => from,
160
+ :to => to,
161
+ :message => out.inspect if out[:exitcode] != 0
162
+ end
163
+
164
+ end #class
165
+ end
166
+ end
@@ -56,35 +56,16 @@ module VagrantWindows
56
56
  def wql(query)
57
57
  execute_wql(query)
58
58
  end
59
-
59
+
60
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
61
+ WinRMFileManager.new(self).upload(from, to)
78
62
  end
79
63
 
80
64
  def download(from, to)
81
- @logger.debug("Downloading: #{from} to #{to}")
82
- output = powershell("[System.convert]::ToBase64String([System.IO.File]::ReadAllBytes(\"#{from}\"))")
83
- contents = output[:data].map!{|line| line[:stdout]}.join.gsub("\\n\\r", '')
84
- out = Base64.decode64(contents)
85
- IO.binwrite(to, out)
65
+ WinRMFileManager.new(self).download(from, to)
86
66
  end
87
67
 
68
+
88
69
  protected
89
70
 
90
71
  def execute_shell(command, shell=:powershell, &block)
@@ -21,7 +21,11 @@ module VagrantWindows
21
21
 
22
22
  class WinRMAuthorizationError < VagrantWindowsError
23
23
  error_key(:winrm_auth_error)
24
- end
24
+ end
25
+
26
+ class WinRMFileTransferError < VagrantWindowsError
27
+ error_key(:winrm_file_transfer_error)
28
+ end
25
29
 
26
30
  end
27
31
  end
@@ -34,11 +34,8 @@ module VagrantPlugins
34
34
  end
35
35
 
36
36
  #################### START - monkey patched code ####################
37
- command_builder = ::VagrantWindows::Provisioners::ChefCommandBuilder.new(
38
- @windows_machine, @config, :client)
39
-
40
- command_builder.prepare_for_chef_run()
41
- command = command_builder.run_chef_command()
37
+ command = ::VagrantWindows::Provisioners::ChefCommandBuilder.new(
38
+ @windows_machine, @config, :client).run_chef_command()
42
39
  ###################### END - monkey patched code ####################
43
40
 
44
41
  @config.attempts.times do |attempt|
@@ -32,11 +32,8 @@ module VagrantPlugins
32
32
  def run_chef_solo_on_windows
33
33
 
34
34
  #################### START - monkey patched code ####################
35
- command_builder = ::VagrantWindows::Provisioners::ChefCommandBuilder.new(
36
- @windows_machine, @config, :solo)
37
-
38
- command_builder.prepare_for_chef_run()
39
- command = command_builder.run_chef_command()
35
+ command = ::VagrantWindows::Provisioners::ChefCommandBuilder.new(
36
+ @windows_machine, @config, :solo).run_chef_command()
40
37
  ###################### END - monkey patched code ####################
41
38
 
42
39
  @config.attempts.times do |attempt|
@@ -34,12 +34,19 @@ module VagrantPlugins
34
34
  end
35
35
  comm.upload(path.to_s, fixed_upload_path)
36
36
 
37
- command = <<-EOH
38
- $old = Get-ExecutionPolicy;
39
- Set-ExecutionPolicy Unrestricted -force;
40
- #{win_friendly_path(fixed_upload_path)}#{args};
41
- Set-ExecutionPolicy $old -force
42
- EOH
37
+ # if powershell script we need to bypass the execution policy
38
+ command = "#{win_friendly_path(fixed_upload_path)}#{args}"
39
+ command = "powershell -executionpolicy bypass -file #{command}" if
40
+ File.extname(fixed_upload_path).downcase == '.ps1'
41
+
42
+ # for priviliged scripts we need wrap it in a scheduled task
43
+ if config.privileged
44
+ command = VagrantWindows.load_script_template('elevated_shell.ps1', :options => {
45
+ :command => command,
46
+ :username => windows_machine.winrm_config.username,
47
+ :password => windows_machine.winrm_config.password
48
+ })
49
+ end
43
50
 
44
51
  # Execute it with sudo
45
52
  comm.sudo(command) do |type, data|