vagrant-unbundled 1.9.1.1 → 1.9.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/CHANGELOG.md +126 -0
  4. data/LICENSE +1 -1
  5. data/README.md +1 -1
  6. data/bin/vagrant +11 -0
  7. data/contrib/bash/completion.sh +9 -9
  8. data/lib/vagrant.rb +4 -2
  9. data/lib/vagrant/action/builtin/box_add.rb +13 -8
  10. data/lib/vagrant/action/builtin/handle_forwarded_port_collisions.rb +67 -14
  11. data/lib/vagrant/action/builtin/provision.rb +10 -5
  12. data/lib/vagrant/action/general/package_setup_files.rb +51 -0
  13. data/lib/vagrant/action/general/package_setup_folders.rb +37 -0
  14. data/lib/vagrant/batch_action.rb +4 -2
  15. data/lib/vagrant/box_collection.rb +17 -5
  16. data/lib/vagrant/bundler.rb +110 -12
  17. data/lib/vagrant/cli.rb +1 -1
  18. data/lib/vagrant/environment.rb +4 -4
  19. data/lib/vagrant/errors.rb +32 -0
  20. data/lib/vagrant/shared_helpers.rb +14 -0
  21. data/lib/vagrant/ui.rb +3 -3
  22. data/lib/vagrant/util.rb +7 -1
  23. data/lib/vagrant/util/command_deprecation.rb +56 -0
  24. data/lib/vagrant/util/credential_scrubber.rb +29 -0
  25. data/lib/vagrant/util/guest_inspection.rb +47 -0
  26. data/lib/vagrant/util/platform.rb +217 -27
  27. data/lib/vagrant/util/powershell.rb +25 -0
  28. data/lib/vagrant/util/safe_exec.rb +9 -1
  29. data/lib/vagrant/util/ssh.rb +1 -1
  30. data/lib/vagrant/util/subprocess.rb +21 -2
  31. data/lib/vagrant/util/which.rb +6 -4
  32. data/plugins/commands/box/command/list.rb +1 -1
  33. data/plugins/commands/package/command.rb +3 -2
  34. data/plugins/commands/plugin/action.rb +2 -1
  35. data/plugins/commands/plugin/action/expunge_plugins.rb +20 -5
  36. data/plugins/commands/plugin/action/install_gem.rb +0 -8
  37. data/plugins/commands/plugin/command/expunge.rb +18 -5
  38. data/plugins/commands/plugin/command/mixin_install_opts.rb +1 -4
  39. data/plugins/commands/plugin/gem_helper.rb +5 -1
  40. data/plugins/commands/up/command.rb +1 -1
  41. data/plugins/commands/validate/command.rb +31 -0
  42. data/plugins/commands/validate/plugin.rb +17 -0
  43. data/plugins/communicators/ssh/communicator.rb +50 -25
  44. data/plugins/communicators/winrm/communicator.rb +8 -54
  45. data/plugins/communicators/winrm/config.rb +3 -0
  46. data/plugins/communicators/winrm/helper.rb +1 -1
  47. data/plugins/communicators/winrm/shell.rb +38 -32
  48. data/plugins/communicators/winssh/communicator.rb +161 -0
  49. data/plugins/communicators/winssh/config.rb +30 -0
  50. data/plugins/communicators/winssh/plugin.rb +21 -0
  51. data/plugins/guests/arch/cap/change_host_name.rb +0 -3
  52. data/plugins/guests/arch/cap/configure_networks.rb +1 -1
  53. data/plugins/guests/atomic/cap/change_host_name.rb +0 -3
  54. data/plugins/guests/darwin/cap/change_host_name.rb +0 -4
  55. data/plugins/guests/debian/cap/change_host_name.rb +0 -3
  56. data/plugins/guests/debian/cap/configure_networks.rb +2 -1
  57. data/plugins/guests/elementary/guest.rb +10 -0
  58. data/plugins/guests/elementary/plugin.rb +15 -0
  59. data/plugins/guests/esxi/cap/public_key.rb +63 -0
  60. data/plugins/guests/esxi/plugin.rb +11 -0
  61. data/plugins/guests/freebsd/cap/change_host_name.rb +0 -4
  62. data/plugins/guests/gentoo/cap/change_host_name.rb +7 -5
  63. data/plugins/guests/gentoo/cap/configure_networks.rb +57 -21
  64. data/plugins/guests/linux/cap/mount_smb_shared_folder.rb +20 -53
  65. data/plugins/guests/linux/cap/mount_virtualbox_shared_folder.rb +10 -58
  66. data/plugins/guests/linux/cap/network_interfaces.rb +8 -1
  67. data/plugins/guests/linux/cap/nfs.rb +5 -14
  68. data/plugins/guests/linux/guest.rb +3 -3
  69. data/plugins/guests/omnios/cap/change_host_name.rb +0 -3
  70. data/plugins/guests/openbsd/cap/change_host_name.rb +0 -4
  71. data/plugins/guests/photon/cap/change_host_name.rb +0 -3
  72. data/plugins/guests/pld/cap/change_host_name.rb +0 -3
  73. data/plugins/guests/redhat/cap/change_host_name.rb +2 -9
  74. data/plugins/guests/redhat/cap/configure_networks.rb +43 -21
  75. data/plugins/guests/slackware/cap/change_host_name.rb +0 -3
  76. data/plugins/guests/suse/cap/change_host_name.rb +0 -3
  77. data/plugins/guests/tinycore/cap/mount_nfs.rb +3 -8
  78. data/plugins/guests/windows/cap/configure_networks.rb +0 -4
  79. data/plugins/guests/windows/cap/mount_shared_folder.rb +13 -1
  80. data/plugins/guests/windows/scripts/mount_volume.ps1.erb +1 -1
  81. data/plugins/hosts/windows/cap/ps.rb +6 -1
  82. data/plugins/kernel_v2/config/vm.rb +6 -4
  83. data/plugins/providers/docker/action.rb +4 -7
  84. data/plugins/providers/docker/action/build.rb +1 -1
  85. data/plugins/providers/docker/action/create.rb +3 -0
  86. data/plugins/providers/docker/config.rb +27 -1
  87. data/plugins/providers/docker/driver.rb +15 -2
  88. data/plugins/providers/docker/driver/compose.rb +287 -0
  89. data/plugins/providers/docker/errors.rb +16 -0
  90. data/plugins/providers/docker/provider.rb +25 -10
  91. data/plugins/providers/hyperv/action.rb +33 -8
  92. data/plugins/providers/hyperv/action/export.rb +39 -0
  93. data/plugins/providers/hyperv/action/import.rb +23 -4
  94. data/plugins/providers/hyperv/action/package.rb +16 -0
  95. data/plugins/providers/hyperv/action/package_metadata_json.rb +34 -0
  96. data/plugins/providers/hyperv/action/package_setup_files.rb +16 -0
  97. data/plugins/providers/hyperv/action/package_setup_folders.rb +18 -0
  98. data/plugins/providers/hyperv/action/package_vagrantfile.rb +34 -0
  99. data/plugins/providers/hyperv/config.rb +20 -4
  100. data/plugins/providers/hyperv/driver.rb +12 -0
  101. data/plugins/providers/hyperv/scripts/export_vm.ps1 +15 -0
  102. data/plugins/providers/hyperv/scripts/get_network_mac.ps1 +28 -0
  103. data/plugins/providers/hyperv/scripts/has_vmcx_support.ps1 +11 -0
  104. data/plugins/providers/hyperv/scripts/import_vm_vmcx.ps1 +10 -4
  105. data/plugins/providers/hyperv/scripts/import_vm_xml.ps1 +9 -3
  106. data/plugins/providers/hyperv/scripts/set_vm_integration_services.ps1 +37 -0
  107. data/plugins/providers/virtualbox/action/package_setup_files.rb +7 -42
  108. data/plugins/providers/virtualbox/action/package_setup_folders.rb +6 -26
  109. data/plugins/providers/virtualbox/driver/base.rb +10 -0
  110. data/plugins/providers/virtualbox/driver/version_5_0.rb +11 -11
  111. data/plugins/providers/virtualbox/driver/version_5_1.rb +3 -721
  112. data/plugins/providers/virtualbox/provider.rb +9 -5
  113. data/plugins/providers/virtualbox/synced_folder.rb +1 -1
  114. data/plugins/providers/virtualbox/util/compile_forwarded_ports.rb +3 -1
  115. data/plugins/provisioners/ansible/cap/guest/arch/ansible_install.rb +2 -2
  116. data/plugins/provisioners/ansible/cap/guest/debian/ansible_install.rb +8 -8
  117. data/plugins/provisioners/ansible/cap/guest/fedora/ansible_install.rb +9 -5
  118. data/plugins/provisioners/ansible/cap/guest/freebsd/ansible_install.rb +1 -1
  119. data/plugins/provisioners/ansible/cap/guest/pip/pip.rb +5 -3
  120. data/plugins/provisioners/ansible/cap/guest/redhat/ansible_install.rb +7 -3
  121. data/plugins/provisioners/ansible/cap/guest/suse/ansible_install.rb +1 -1
  122. data/plugins/provisioners/ansible/cap/guest/ubuntu/ansible_install.rb +3 -3
  123. data/plugins/provisioners/ansible/config/guest.rb +7 -1
  124. data/plugins/provisioners/ansible/provisioner/guest.rb +1 -1
  125. data/plugins/provisioners/chef/cap/freebsd/chef_install.rb +18 -0
  126. data/plugins/provisioners/chef/cap/freebsd/chef_installed.rb +22 -0
  127. data/plugins/provisioners/chef/plugin.rb +10 -0
  128. data/plugins/provisioners/docker/cap/linux/docker_installed.rb +1 -0
  129. data/plugins/provisioners/salt/bootstrap-salt.ps1 +4 -4
  130. data/plugins/provisioners/shell/config.rb +2 -2
  131. data/plugins/provisioners/shell/provisioner.rb +66 -4
  132. data/plugins/pushes/atlas/push.rb +6 -0
  133. data/plugins/pushes/local-exec/config.rb +2 -2
  134. data/plugins/synced_folders/unix_mount_helpers.rb +105 -0
  135. data/templates/commands/init/Vagrantfile.erb +6 -0
  136. data/templates/commands/init/Vagrantfile.min.erb +3 -0
  137. data/templates/guests/debian/network_dhcp.erb +2 -2
  138. data/templates/guests/gentoo/network_systemd.erb +16 -0
  139. data/templates/guests/redhat/network_dhcp.erb +1 -0
  140. data/templates/guests/redhat/network_static.erb +1 -1
  141. data/templates/guests/redhat/network_static6.erb +1 -1
  142. data/templates/locales/en.yml +72 -3
  143. data/templates/locales/providers_docker.yml +15 -0
  144. data/test/acceptance/provider-virtualbox/linked_clone_spec.rb +1 -1
  145. data/test/unit/plugins/commands/init/command_test.rb +7 -0
  146. data/test/unit/plugins/commands/up/command_test.rb +65 -0
  147. data/test/unit/plugins/commands/validate/command_test.rb +52 -0
  148. data/test/unit/plugins/communicators/ssh/communicator_test.rb +58 -2
  149. data/test/unit/plugins/communicators/winrm/communicator_test.rb +14 -26
  150. data/test/unit/plugins/communicators/winrm/helper_test.rb +12 -0
  151. data/test/unit/plugins/communicators/winrm/shell_test.rb +54 -15
  152. data/test/unit/plugins/communicators/winssh/communicator_test.rb +525 -0
  153. data/test/unit/plugins/guests/arch/cap/configure_networks_test.rb +5 -0
  154. data/test/unit/plugins/guests/esxi/cap/public_key_test.rb +48 -0
  155. data/test/unit/plugins/guests/linux/cap/mount_nfs_test.rb +1 -1
  156. data/test/unit/plugins/guests/linux/cap/mount_smb_shared_folder.rb +71 -0
  157. data/test/unit/plugins/guests/linux/cap/mount_virtual_box_shared_folder_test.rb +43 -0
  158. data/test/unit/plugins/guests/linux/cap/network_interfaces_test.rb +10 -10
  159. data/test/unit/plugins/guests/redhat/cap/configure_networks_test.rb +132 -12
  160. data/test/unit/plugins/guests/windows/cap/mount_shared_folder_test.rb +23 -0
  161. data/test/unit/plugins/providers/docker/driver_compose_test.rb +268 -0
  162. data/test/unit/plugins/provisioners/ansible/config/guest_test.rb +9 -0
  163. data/test/unit/plugins/provisioners/ansible/provisioner_test.rb +2 -2
  164. data/test/unit/plugins/pushes/atlas/push_test.rb +151 -150
  165. data/test/unit/templates/guests/debian/network_dhcp_test.rb +1 -0
  166. data/test/unit/templates/guests/gentoo/systemd_network_test.rb +73 -0
  167. data/test/unit/templates/guests/redhat/network_dhcp_test.rb +18 -0
  168. data/test/unit/vagrant/action/builtin/box_add_test.rb +27 -0
  169. data/test/unit/vagrant/action/builtin/handle_forwarded_port_collisions_test.rb +170 -0
  170. data/test/unit/vagrant/action/builtin/provision_test.rb +208 -0
  171. data/test/unit/vagrant/box_collection_test.rb +98 -0
  172. data/test/unit/vagrant/environment_test.rb +17 -0
  173. data/test/unit/vagrant/shared_helpers_test.rb +12 -0
  174. data/test/unit/vagrant/util/command_deprecation_test.rb +106 -0
  175. data/test/unit/vagrant/util/env_test.rb +43 -0
  176. data/test/unit/vagrant/util/platform_test.rb +8 -0
  177. data/test/unit/vagrant/util/subprocess_test.rb +61 -0
  178. data/test/vagrant-spec/Vagrantfile.spec +78 -0
  179. data/test/vagrant-spec/boxes/.keep +0 -0
  180. data/test/vagrant-spec/configs/vagrant-spec.config.virtualbox.rb +10 -0
  181. data/test/vagrant-spec/scripts/centos-run.virtualbox.sh +8 -0
  182. data/test/vagrant-spec/scripts/centos-setup.virtualbox.sh +14 -0
  183. data/test/vagrant-spec/scripts/ubuntu-run.virtualbox.sh +8 -0
  184. data/test/vagrant-spec/scripts/ubuntu-setup.virtualbox.sh +12 -0
  185. data/vagrant.gemspec +6 -11
  186. data/version.txt +1 -1
  187. metadata +1694 -1835
  188. data/plugins/communicators/winrm/scripts/elevated_shell.ps1.erb +0 -101
@@ -142,10 +142,10 @@ module VagrantPlugins
142
142
  interactive: false,
143
143
  }.merge(opts || {})
144
144
 
145
+ opts[:shell] = :elevated if opts[:elevated]
145
146
  opts[:good_exit] = Array(opts[:good_exit])
146
- command = wrap_in_scheduled_task(command, opts[:interactive]) if opts[:elevated]
147
147
  @logger.debug("#{opts[:shell]} executing:\n#{command}")
148
- output = shell.send(opts[:shell], command, &block)
148
+ output = shell.send(opts[:shell], command, opts, &block)
149
149
  execution_output(output, opts)
150
150
  end
151
151
  alias_method :sudo, :execute
@@ -165,7 +165,7 @@ module VagrantPlugins
165
165
  # If we're passed a *nix command which PS can't parse we get exit code
166
166
  # 0, but output in stderr. We need to check both exit code and stderr.
167
167
  output = shell.send(:powershell, command)
168
- return output[:exitcode] == 0 && flatten_stderr(output).length == 0
168
+ return output.exitcode == 0 && output.stderr.length == 0
169
169
  end
170
170
 
171
171
  def upload(from, to)
@@ -180,7 +180,7 @@ module VagrantPlugins
180
180
 
181
181
  protected
182
182
 
183
- # This creates anew WinRMShell based on the information we know
183
+ # This creates a new WinRMShell based on the information we know
184
184
  # about this machine.
185
185
  def create_shell
186
186
  winrm_info = Helper.winrm_info(@machine)
@@ -192,55 +192,23 @@ module VagrantPlugins
192
192
  )
193
193
  end
194
194
 
195
- # Creates and uploads a PowerShell script which wraps a command in a
196
- # scheduled task. The scheduled task allows commands to run on the guest
197
- # as a true local admin without any of the restrictions that WinRM puts
198
- # in place.
199
- #
200
- # @return The wrapper command to execute
201
- def wrap_in_scheduled_task(command, interactive)
202
- path = File.expand_path("../scripts/elevated_shell.ps1", __FILE__)
203
- script = Vagrant::Util::TemplateRenderer.render(path, options: {
204
- interactive: interactive,
205
- })
206
- guest_script_path = "c:/tmp/vagrant-elevated-shell.ps1"
207
- Tempfile.open(["vagrant-elevated-shell", "ps1"]) do |f|
208
- f.binmode
209
- f.write(script)
210
- f.fsync
211
- f.close
212
- upload(f.path, guest_script_path)
213
- end
214
-
215
- # Convert to double byte unicode string then base64 encode
216
- # just like PowerShell -EncodedCommand expects.
217
- # Suppress the progress stream from leaking to stderr.
218
- wrapped_encoded_command = Base64.strict_encode64(
219
- "$ProgressPreference='SilentlyContinue'; #{command}; exit $LASTEXITCODE".encode('UTF-16LE', 'UTF-8'))
220
-
221
- "powershell -executionpolicy bypass -file '#{guest_script_path}' " +
222
- "-username '#{shell.username}' -password '#{shell.password}' " +
223
- "-encoded_command '#{wrapped_encoded_command}' " +
224
- "-execution_time_limit '#{shell.execution_time_limit}'"
225
- end
226
-
227
195
  # Handles the raw WinRM shell result and converts it to a
228
196
  # standard Vagrant communicator result
229
197
  def execution_output(output, opts)
230
198
  if opts[:shell] == :wql
231
199
  return output
232
200
  elsif opts[:error_check] && \
233
- !opts[:good_exit].include?(output[:exitcode])
201
+ !opts[:good_exit].include?(output.exitcode)
234
202
  raise_execution_error(output, opts)
235
203
  end
236
- output[:exitcode]
204
+ output.exitcode
237
205
  end
238
206
 
239
207
  def raise_execution_error(output, opts)
240
208
  # WinRM can return multiple stderr and stdout entries
241
209
  error_opts = opts.merge(
242
- stdout: flatten_stdout(output),
243
- stderr: flatten_stderr(output)
210
+ stdout: output.stdout,
211
+ stderr: output.stderr
244
212
  )
245
213
 
246
214
  # Use a different error message key if the caller gave us one,
@@ -250,20 +218,6 @@ module VagrantPlugins
250
218
  # Raise the error, use the type the caller gave us or the comm default
251
219
  raise opts[:error_class], error_opts
252
220
  end
253
-
254
-
255
- # TODO: Replace with WinRM Output class when WinRM 1.3 is released
256
- def flatten_stderr(output)
257
- output[:data].map do | line |
258
- line[:stderr]
259
- end.compact.join
260
- end
261
-
262
- def flatten_stdout(output)
263
- output[:data].map do | line |
264
- line[:flatten_stdout]
265
- end.compact.join
266
- end
267
221
  end #WinRM class
268
222
  end
269
223
  end
@@ -13,6 +13,7 @@ module VagrantPlugins
13
13
  attr_accessor :ssl_peer_verification
14
14
  attr_accessor :execution_time_limit
15
15
  attr_accessor :basic_auth_only
16
+ attr_accessor :codepage
16
17
 
17
18
  def initialize
18
19
  @username = UNSET_VALUE
@@ -27,6 +28,7 @@ module VagrantPlugins
27
28
  @ssl_peer_verification = UNSET_VALUE
28
29
  @execution_time_limit = UNSET_VALUE
29
30
  @basic_auth_only = UNSET_VALUE
31
+ @codepage = UNSET_VALUE
30
32
  end
31
33
 
32
34
  def finalize!
@@ -43,6 +45,7 @@ module VagrantPlugins
43
45
  @ssl_peer_verification = true if @ssl_peer_verification == UNSET_VALUE
44
46
  @execution_time_limit = "PT2H" if @execution_time_limit == UNSET_VALUE
45
47
  @basic_auth_only = false if @basic_auth_only == UNSET_VALUE
48
+ @codepage = nil if @codepage == UNSET_VALUE
46
49
  end
47
50
 
48
51
  def validate(machine)
@@ -33,7 +33,7 @@ module VagrantPlugins
33
33
  return addr if addr
34
34
 
35
35
  ssh_info = machine.ssh_info
36
- raise Errors::WinRMNotReady if !ssh_info
36
+ raise Errors::WinRMNotReady if !ssh_info || ssh_info[:host].to_s.empty?
37
37
  return ssh_info[:host]
38
38
  end
39
39
 
@@ -9,6 +9,7 @@ Vagrant::Util::SilenceWarnings.silence! do
9
9
  require "winrm"
10
10
  end
11
11
 
12
+ require "winrm-elevated"
12
13
  require "winrm-fs"
13
14
 
14
15
  module VagrantPlugins
@@ -53,48 +54,55 @@ module VagrantPlugins
53
54
  @config = config
54
55
  end
55
56
 
56
- def powershell(command, &block)
57
- # Ensure an exit code
58
- command += "\r\nif ($?) { exit 0 } else { if($LASTEXITCODE) { exit $LASTEXITCODE } else { exit 1 } }"
59
- session.create_executor do |executor|
60
- execute_with_rescue(executor.method("run_powershell_script"), command, &block)
57
+ def powershell(command, opts = {}, &block)
58
+ connection.shell(:powershell) do |shell|
59
+ execute_with_rescue(shell, command, &block)
61
60
  end
62
61
  end
63
62
 
64
- def cmd(command, &block)
65
- session.create_executor do |executor|
66
- execute_with_rescue(executor.method("run_cmd"), command, &block)
63
+ def cmd(command, opts = {}, &block)
64
+ shell_opts = {}
65
+ shell_opts[:codepage] = @config.codepage if @config.codepage
66
+ connection.shell(:cmd, shell_opts) do |shell|
67
+ execute_with_rescue(shell, command, &block)
67
68
  end
68
69
  end
69
70
 
70
- def wql(query, &block)
71
+ def elevated(command, opts = {}, &block)
72
+ connection.shell(:elevated) do |shell|
73
+ shell.interactive_logon = opts[:interactive] || false
74
+ execute_with_rescue(shell, command, &block)
75
+ end
76
+ end
77
+
78
+ def wql(query, opts = {}, &block)
71
79
  retryable(tries: @config.max_tries, on: @@exceptions_to_retry_on, sleep: @config.retry_delay) do
72
- handle_output(session.method("run_wql"), query, &block)
80
+ connection.run_wql(query)
73
81
  end
74
82
  rescue => e
75
83
  raise_winrm_exception(e, "run_wql", query)
76
84
  end
77
85
 
78
86
  def upload(from, to)
79
- file_manager = WinRM::FS::FileManager.new(session)
87
+ file_manager = WinRM::FS::FileManager.new(connection)
80
88
  file_manager.upload(from, to)
81
89
  end
82
90
 
83
91
  def download(from, to)
84
- file_manager = WinRM::FS::FileManager.new(session)
92
+ file_manager = WinRM::FS::FileManager.new(connection)
85
93
  file_manager.download(from, to)
86
94
  end
87
95
 
88
96
  protected
89
97
 
90
- def execute_with_rescue(method, command, &block)
91
- handle_output(method, command, &block)
98
+ def execute_with_rescue(shell, command, &block)
99
+ handle_output(shell, command, &block)
92
100
  rescue => e
93
- raise_winrm_exception(e, method.name, command)
101
+ raise_winrm_exception(e, shell.class.name.split("::").last, command)
94
102
  end
95
103
 
96
- def handle_output(execute_method, command, &block)
97
- output = execute_method.call(command) do |out, err|
104
+ def handle_output(shell, command, &block)
105
+ output = shell.run(command) do |out, err|
98
106
  block.call(:stdout, out) if block_given? && out
99
107
  block.call(:stderr, err) if block_given? && err
100
108
  end
@@ -104,14 +112,10 @@ module VagrantPlugins
104
112
  # Verify that we didn't get a parser error, and if so we should
105
113
  # set the exit code to 1. Parse errors return exit code 0 so we
106
114
  # need to do this.
107
- if output[:exitcode] == 0
108
- (output[:data] || []).each do |data|
109
- next if !data[:stderr]
110
- if data[:stderr].include?("ParserError")
111
- @logger.warn("Detected ParserError, setting exit code to 1")
112
- output[:exitcode] = 1
113
- break
114
- end
115
+ if output.exitcode == 0
116
+ if output.stderr.include?("ParserError")
117
+ @logger.warn("Detected ParserError, setting exit code to 1")
118
+ output.exitcode = 1
115
119
  end
116
120
  end
117
121
 
@@ -159,21 +163,20 @@ module VagrantPlugins
159
163
  end
160
164
  end
161
165
 
162
- def new_session
166
+ def new_connection
163
167
  @logger.info("Attempting to connect to WinRM...")
164
168
  @logger.info(" - Host: #{@host}")
165
169
  @logger.info(" - Port: #{@port}")
166
170
  @logger.info(" - Username: #{@config.username}")
167
171
  @logger.info(" - Transport: #{@config.transport}")
168
172
 
169
- client = ::WinRM::WinRMWebService.new(endpoint, @config.transport.to_sym, endpoint_options)
170
- client.set_timeout(@config.timeout)
173
+ client = ::WinRM::Connection.new(endpoint_options)
171
174
  client.logger = @logger
172
175
  client
173
176
  end
174
177
 
175
- def session
176
- @session ||= new_session
178
+ def connection
179
+ @connection ||= new_connection
177
180
  end
178
181
 
179
182
  def endpoint
@@ -188,8 +191,11 @@ module VagrantPlugins
188
191
  end
189
192
 
190
193
  def endpoint_options
191
- { user: @username,
192
- pass: @password,
194
+ { endpoint: endpoint,
195
+ transport: @config.transport,
196
+ operation_timeout: @config.timeout,
197
+ user: @username,
198
+ password: @password,
193
199
  host: @host,
194
200
  port: @port,
195
201
  basic_auth_only: @config.basic_auth_only,
@@ -0,0 +1,161 @@
1
+ require File.expand_path("../../ssh/communicator", __FILE__)
2
+
3
+ module VagrantPlugins
4
+ module CommunicatorWinSSH
5
+ # This class provides communication with a Windows VM running
6
+ # the Windows native port of OpenSSH
7
+ class Communicator < VagrantPlugins::CommunicatorSSH::Communicator
8
+
9
+ def initialize(machine)
10
+ super
11
+ @logger = Log4r::Logger.new("vagrant::communication::winssh")
12
+ end
13
+
14
+ # Executes the command on an SSH connection within a login shell.
15
+ def shell_execute(connection, command, **opts)
16
+ opts = {
17
+ sudo: false,
18
+ shell: nil
19
+ }.merge(opts)
20
+
21
+ sudo = opts[:sudo]
22
+ shell = (opts[:shell] || machine_config_ssh.shell).to_s
23
+
24
+ @logger.info("Execute: #{command} (sudo=#{sudo.inspect})")
25
+ exit_status = nil
26
+
27
+ # Open the channel so we can execute or command
28
+ channel = connection.open_channel do |ch|
29
+ marker_found = false
30
+ data_buffer = ''
31
+ stderr_marker_found = false
32
+ stderr_data_buffer = ''
33
+
34
+ tfile = Tempfile.new('vagrant-ssh')
35
+ remote_ext = shell == "powershell" ? "ps1" : "bat"
36
+ remote_name = "C:\\Windows\\Temp\\#{File.basename(tfile.path)}.#{remote_ext}"
37
+
38
+ if shell == "powershell"
39
+ base_cmd = "powershell -File #{remote_name}"
40
+ tfile.puts <<-SCRIPT.force_encoding('ASCII-8BIT')
41
+ Remove-Item #{remote_name}
42
+ Write-Host #{CMD_GARBAGE_MARKER}
43
+ [Console]::Error.WriteLine("#{CMD_GARBAGE_MARKER}")
44
+ #{command}
45
+ SCRIPT
46
+ else
47
+ base_cmd = remote_name
48
+ tfile.puts <<-SCRIPT.force_encoding('ASCII-8BIT')
49
+ ECHO OFF
50
+ ECHO #{CMD_GARBAGE_MARKER}
51
+ ECHO #{CMD_GARBAGE_MARKER} 1>&2
52
+ #{command}
53
+ SCRIPT
54
+ end
55
+
56
+ tfile.close
57
+ upload(tfile.path, remote_name)
58
+ tfile.delete
59
+
60
+ base_cmd = shell_cmd(opts.merge(shell: base_cmd))
61
+ @logger.debug("Base SSH exec command: #{base_cmd}")
62
+
63
+ ch.exec(base_cmd) do |ch2, _|
64
+ # Setup the channel callbacks so we can get data and exit status
65
+ ch2.on_data do |ch3, data|
66
+ # Filter out the clear screen command
67
+ data = remove_ansi_escape_codes(data)
68
+
69
+ if !marker_found
70
+ data_buffer << data
71
+ marker_index = data_buffer.index(CMD_GARBAGE_MARKER)
72
+ if marker_index
73
+ marker_found = true
74
+ data_buffer.slice!(0, marker_index + CMD_GARBAGE_MARKER.size)
75
+ data.replace(data_buffer)
76
+ data_buffer = nil
77
+ end
78
+ end
79
+
80
+ if block_given? && marker_found
81
+ yield :stdout, data
82
+ end
83
+ end
84
+
85
+ ch2.on_extended_data do |ch3, type, data|
86
+ # Filter out the clear screen command
87
+ data = remove_ansi_escape_codes(data)
88
+ @logger.debug("stderr: #{data}")
89
+ if !stderr_marker_found
90
+ stderr_data_buffer << data
91
+ marker_index = stderr_data_buffer.index(CMD_GARBAGE_MARKER)
92
+ if marker_index
93
+ marker_found = true
94
+ stderr_data_buffer.slice!(0, marker_index + CMD_GARBAGE_MARKER.size)
95
+ data.replace(stderr_data_buffer.lstrip)
96
+ data_buffer = nil
97
+ end
98
+ end
99
+
100
+ if block_given? && marker_found
101
+ yield :stderr, data
102
+ end
103
+ end
104
+
105
+ ch2.on_request("exit-status") do |ch3, data|
106
+ exit_status = data.read_long
107
+ @logger.debug("Exit status: #{exit_status}")
108
+
109
+ # Close the channel, since after the exit status we're
110
+ # probably done. This fixes up issues with hanging.
111
+ ch.close
112
+ end
113
+
114
+ end
115
+ end
116
+
117
+ begin
118
+ keep_alive = nil
119
+
120
+ if @machine.config.ssh.keep_alive
121
+ # Begin sending keep-alive packets while we wait for the script
122
+ # to complete. This avoids connections closing on long-running
123
+ # scripts.
124
+ keep_alive = Thread.new do
125
+ loop do
126
+ sleep 5
127
+ @logger.debug("Sending SSH keep-alive...")
128
+ connection.send_global_request("keep-alive@openssh.com")
129
+ end
130
+ end
131
+ end
132
+
133
+ # Wait for the channel to complete
134
+ begin
135
+ channel.wait
136
+ rescue Errno::ECONNRESET, IOError
137
+ @logger.info(
138
+ "SSH connection unexpected closed. Assuming reboot or something.")
139
+ exit_status = 0
140
+ pty = false
141
+ rescue Net::SSH::ChannelOpenFailed
142
+ raise Vagrant::Errors::SSHChannelOpenFail
143
+ rescue Net::SSH::Disconnect
144
+ raise Vagrant::Errors::SSHDisconnected
145
+ end
146
+ ensure
147
+ # Kill the keep-alive thread
148
+ keep_alive.kill if keep_alive
149
+ end
150
+
151
+ # Return the final exit status
152
+ return exit_status
153
+ end
154
+
155
+ def machine_config_ssh
156
+ @machine.config.winssh
157
+ end
158
+
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,30 @@
1
+ require File.expand_path("../../../kernel_v2/config/ssh", __FILE__)
2
+
3
+ module VagrantPlugins
4
+ module CommunicatorWinSSH
5
+ class Config < VagrantPlugins::Kernel_V2::SSHConfig
6
+
7
+ def finalize!
8
+ @shell = "cmd" if @shell == UNSET_VALUE
9
+ @sudo_command = "%c" if @sudo_command == UNSET_VALUE
10
+ if @export_command_template == UNSET_VALUE
11
+ if @shell == "cmd"
12
+ @export_command_template = 'set %ENV_KEY%="%ENV_VALUE%"'
13
+ else
14
+ @export_command_template = '$env:%ENV_KEY%="%ENV_VALUE%"'
15
+ end
16
+ end
17
+ super
18
+ end
19
+
20
+ def to_s
21
+ "WINSSH"
22
+ end
23
+
24
+ # Remove configuration options from regular SSH that are
25
+ # not used within this communicator
26
+ undef :forward_x11
27
+ undef :pty
28
+ end
29
+ end
30
+ end