vagrant-windows 1.6.0 → 1.7.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
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|