vagrant-windows 1.0.3 → 1.2.0

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 (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +1 -1
  5. data/README.md +77 -20
  6. data/Rakefile +14 -4
  7. data/lib/vagrant-windows/communication/guestnetwork.rb +133 -0
  8. data/lib/vagrant-windows/communication/winrmcommunicator.rb +56 -151
  9. data/lib/vagrant-windows/communication/winrmfinder.rb +45 -0
  10. data/lib/vagrant-windows/communication/winrmshell.rb +141 -0
  11. data/lib/vagrant-windows/config/windows.rb +4 -0
  12. data/lib/vagrant-windows/config/winrm.rb +1 -1
  13. data/lib/vagrant-windows/guest/cap/change_host_name.rb +14 -0
  14. data/lib/vagrant-windows/guest/cap/configure_networks.rb +69 -0
  15. data/lib/vagrant-windows/guest/cap/halt.rb +22 -0
  16. data/lib/vagrant-windows/guest/cap/mount_virtualbox_shared_folder.rb +17 -0
  17. data/lib/vagrant-windows/guest/cap/mount_vmware_shared_folder.rb +15 -0
  18. data/lib/vagrant-windows/guest/windows.rb +46 -77
  19. data/lib/vagrant-windows/helper.rb +6 -0
  20. data/lib/vagrant-windows/monkey_patches/{machine.rb → lib/vagrant/machine.rb} +7 -0
  21. data/lib/vagrant-windows/monkey_patches/plugins/providers/virtualbox/action/share_folders.rb +44 -0
  22. data/lib/vagrant-windows/monkey_patches/{vbox_42_driver.rb → plugins/providers/virtualbox/driver/version_4_2.rb} +0 -0
  23. data/lib/vagrant-windows/monkey_patches/plugins/provisioners/chef/provisioner/chef_client.rb +1 -0
  24. data/lib/vagrant-windows/monkey_patches/plugins/provisioners/chef/provisioner/chef_solo.rb +106 -0
  25. data/lib/vagrant-windows/monkey_patches/{puppet.rb → plugins/provisioners/puppet/provisioner/puppet.rb} +5 -4
  26. data/lib/vagrant-windows/monkey_patches/plugins/provisioners/puppet/provisioner/puppet_server.rb +1 -0
  27. data/lib/vagrant-windows/monkey_patches/{provisioner.rb → plugins/provisioners/shell/provisioner.rb} +4 -4
  28. data/lib/vagrant-windows/plugin.rb +54 -27
  29. data/lib/vagrant-windows/scripts/cheftask.ps1.erb +47 -0
  30. data/lib/vagrant-windows/scripts/cheftask.xml.erb +45 -0
  31. data/lib/vagrant-windows/scripts/cheftaskrun.ps1.erb +16 -0
  32. data/lib/vagrant-windows/scripts/command_alias.ps1 +4 -0
  33. data/lib/vagrant-windows/scripts/{mount_volume.ps1.erb → mount_volume.virtualbox.ps1.erb} +1 -1
  34. data/lib/vagrant-windows/scripts/mount_volume.vmware.ps1.erb +49 -0
  35. data/lib/vagrant-windows/scripts/set_work_network.ps1 +6 -0
  36. data/lib/vagrant-windows/scripts/winrs_v3_get_adapters.ps1 +11 -0
  37. data/lib/vagrant-windows/version.rb +1 -1
  38. data/spec/spec_helper.rb +14 -0
  39. data/spec/vagrant-windows/config_spec.rb +3 -4
  40. data/spec/vagrant-windows/guestnetwork_spec.rb +47 -0
  41. data/spec/vagrant-windows/helper_spec.rb +14 -3
  42. data/spec/vagrant-windows/winrmcommunicator_spec.rb +26 -0
  43. data/vagrant-windows.gemspec +33 -2
  44. metadata +100 -55
  45. data/lib/vagrant-windows/monkey_patches/chef_solo.rb +0 -61
  46. data/lib/vagrant-windows/scripts/ps_runas.ps1.erb +0 -56
@@ -1,5 +1,6 @@
1
1
  module VagrantWindows
2
2
  module Helper
3
+ extend self
3
4
 
4
5
  def win_friendly_path(path)
5
6
  if path
@@ -8,6 +9,11 @@ module VagrantWindows
8
9
  end
9
10
  new_path
10
11
  end
12
+
13
+ # turns '/vagrant' into 'vagrant' or turns ''/a/b/c/d/e' into 'a_b_c_d_e'
14
+ def win_friendly_share_id(shared_folder_name)
15
+ return shared_folder_name.gsub(/[\/\/]/,'_').sub(/^_/, '')
16
+ end
11
17
 
12
18
  end
13
19
  end
@@ -1,3 +1,6 @@
1
+ require_relative '../../../helper'
2
+ require_relative '../../../communication/winrmcommunicator'
3
+
1
4
  module Vagrant
2
5
  class Machine
3
6
 
@@ -21,5 +24,9 @@ module Vagrant
21
24
  @winrm ||= WinRM.new(self)
22
25
  end
23
26
 
27
+ def is_windows?
28
+ return @config.vm.guest.eql? :windows
29
+ end
30
+
24
31
  end
25
32
  end
@@ -0,0 +1,44 @@
1
+ require "#{Vagrant::source_root}/plugins/providers/virtualbox/action/share_folders"
2
+ require_relative '../../../../../helper'
3
+
4
+ module VagrantPlugins
5
+ module ProviderVirtualBox
6
+ module Action
7
+ class ShareFolders
8
+ include VagrantWindows::Helper
9
+
10
+ alias_method :original_create_metadata, :create_metadata
11
+
12
+ def create_metadata
13
+
14
+ unless @env[:machine].is_windows?
15
+ # don't change the shared folder name for linux guests. We don't want the shared folder name of linux guests to be different
16
+ # depending on whether the vagrant-windows plugin is installed or not.
17
+ original_create_metadata
18
+ else
19
+ @env[:ui].info I18n.t("vagrant.actions.vm.share_folders.creating")
20
+
21
+ folders = []
22
+ shared_folders.each do |id, data|
23
+ hostpath = File.expand_path(data[:hostpath], @env[:root_path])
24
+ hostpath = Vagrant::Util::Platform.cygwin_windows_path(hostpath)
25
+
26
+ folder_name = win_friendly_share_id(id.gsub(/[\/\/]/,'_').sub(/^_/, ''))
27
+
28
+ folders << {
29
+ :name => folder_name,
30
+ :hostpath => hostpath,
31
+ :transient => data[:transient]
32
+ }
33
+ end
34
+
35
+ @env[:machine].provider.driver.share_folders(folders)
36
+ end
37
+ end
38
+
39
+
40
+
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,106 @@
1
+ require 'tempfile'
2
+ require "#{Vagrant::source_root}/plugins/provisioners/chef/provisioner/chef_solo"
3
+ require_relative '../../../../../helper'
4
+
5
+ module VagrantPlugins
6
+ module Chef
7
+ module Provisioner
8
+ class ChefSolo < Base
9
+
10
+ include VagrantWindows::Helper
11
+
12
+ run_chef_solo_on_linux = instance_method(:run_chef_solo)
13
+
14
+ # This patch is needed until Vagrant supports chef on Windows guests
15
+ define_method(:run_chef_solo) do
16
+ is_windows ? run_chef_solo_on_windows() : run_chef_solo_on_linux.bind(self).()
17
+ end
18
+
19
+ def run_chef_solo_on_windows
20
+ # create cheftaskrun.ps1 that the scheduled task will invoke when run
21
+ render_file_and_upload("cheftaskrun.ps1", chef_script_options[:chef_task_run_ps1], :options => chef_script_options)
22
+
23
+ # create cheftask.xml that the scheduled task will be created with
24
+ render_file_and_upload("cheftask.xml", chef_script_options[:chef_task_xml], :options => chef_script_options)
25
+
26
+ # create cheftask.ps1 that will immediately invoke the scheduled task and wait for completion
27
+ render_file_and_upload("cheftask.ps1", chef_script_options[:chef_task_ps1], :options => chef_script_options)
28
+
29
+ command = <<-EOH
30
+ $old = Get-ExecutionPolicy;
31
+ Set-ExecutionPolicy Unrestricted -force;
32
+ #{chef_script_options[:chef_task_ps1]};
33
+ Set-ExecutionPolicy $old -force
34
+ exit $LASTEXITCODE
35
+ EOH
36
+
37
+ @config.attempts.times do |attempt|
38
+ if attempt == 0
39
+ @machine.env.ui.info I18n.t("vagrant.provisioners.chef.running_solo")
40
+ else
41
+ @machine.env.ui.info I18n.t("vagrant.provisioners.chef.running_solo_again")
42
+ end
43
+
44
+ exit_status = @machine.communicate.execute(command) do |type, data|
45
+ # Output the data with the proper color based on the stream.
46
+ color = type == :stdout ? :green : :red
47
+
48
+ @machine.env.ui.info(
49
+ data, :color => color, :new_line => false, :prefix => false)
50
+ end
51
+
52
+ # There is no need to run Chef again if it converges
53
+ return if exit_status == 0
54
+ end
55
+
56
+ # If we reached this point then Chef never converged! Error.
57
+ raise ChefError, :no_convergence
58
+ end
59
+
60
+ def render_file_and_upload(script_name, dest_file, options)
61
+ script_contents = VagrantWindows.load_script_template(script_name, options)
62
+
63
+ # render cheftaskrun.ps1 to local temp file
64
+ script_local = Tempfile.new(script_name)
65
+ IO.write(script_local, script_contents)
66
+
67
+ # upload cheftaskrun.ps1 file
68
+ @machine.communicate.upload(script_local, dest_file)
69
+ end
70
+
71
+ def chef_script_options
72
+ if @chef_script_options.nil?
73
+ command_env = @config.binary_env ? "#{@config.binary_env} " : ""
74
+ command_args = @config.arguments ? " #{@config.arguments}" : ""
75
+ chef_solo_path = win_friendly_path(File.join(@config.provisioning_path, 'solo.rb'))
76
+ chef_dna_path = win_friendly_path(File.join(@config.provisioning_path, 'dna.json'))
77
+
78
+ chef_arguments = "-c #{chef_solo_path} "
79
+ chef_arguments << "-j #{chef_dna_path} "
80
+ chef_arguments << "#{command_args}"
81
+
82
+ @chef_script_options = {
83
+ :user => @machine.config.winrm.username,
84
+ :pass => @machine.config.winrm.password,
85
+ :chef_arguments => chef_arguments,
86
+ :chef_task_xml => win_friendly_path("#{@config.provisioning_path}/cheftask.xml"),
87
+ :chef_task_running => win_friendly_path("#{@config.provisioning_path}/cheftask.running"),
88
+ :chef_task_exitcode => win_friendly_path("#{@config.provisioning_path}/cheftask.exitcode"),
89
+ :chef_task_ps1 => win_friendly_path("#{@config.provisioning_path}/cheftask.ps1"),
90
+ :chef_task_run_ps1 => win_friendly_path("#{@config.provisioning_path}/cheftaskrun.ps1"),
91
+ :chef_stdout_log => win_friendly_path("#{@config.provisioning_path}/chef-solo.log"),
92
+ :chef_stderr_log => win_friendly_path("#{@config.provisioning_path}/chef-solo.err.log"),
93
+ :chef_binary_path => win_friendly_path("#{command_env}#{chef_binary_path("chef-solo")}")
94
+ }
95
+ end
96
+ @chef_script_options
97
+ end
98
+
99
+ def is_windows
100
+ @machine.config.vm.guest.eql? :windows
101
+ end
102
+
103
+ end # ChefSolo class
104
+ end
105
+ end
106
+ end
@@ -22,7 +22,7 @@ module VagrantPlugins
22
22
  module_paths = @module_paths.map { |_, to| to }
23
23
  if !@module_paths.empty?
24
24
  # Prepend the default module path
25
- module_paths.unshift("/etc/puppet/modules")
25
+ module_paths.unshift("/ProgramData/PuppetLabs/puppet/etc/modules")
26
26
 
27
27
  # Add the command line switch to add the module path
28
28
  options << "--modulepath '#{module_paths.join(';')}'"
@@ -48,8 +48,9 @@ module VagrantPlugins
48
48
  :manifest => @manifest_file)
49
49
 
50
50
  @machine.communicate.sudo(command) do |type, data|
51
- data.chomp!
52
- @machine.env.ui.info(data, :prefix => false) if !data.empty?
51
+ if !data.empty?
52
+ @machine.env.ui.info(data, :new_line => false, :prefix => false)
53
+ end
53
54
  end
54
55
  end
55
56
 
@@ -63,7 +64,7 @@ module VagrantPlugins
63
64
  # Setup the module paths
64
65
  @module_paths = []
65
66
  @expanded_module_paths.each_with_index do |path, i|
66
- @module_paths << [path, File.join(config.pp_path, "modules-#{i}")]
67
+ @module_paths << [path, File.join(config.temp_dir, "modules-#{i}")]
67
68
  end
68
69
 
69
70
  @logger.debug("Syncing folders from puppet configure")
@@ -1,5 +1,5 @@
1
1
  require "#{Vagrant::source_root}/plugins/provisioners/shell/provisioner"
2
- require "vagrant-windows/helper"
2
+ require_relative '../../../../helper'
3
3
 
4
4
  module VagrantPlugins
5
5
  module Shell
@@ -43,9 +43,9 @@ module VagrantPlugins
43
43
  # Output the data with the proper color based on the stream.
44
44
  color = type == :stdout ? :green : :red
45
45
 
46
- # Note: Be sure to chomp the data to avoid the newlines that the
47
- # Chef outputs.
48
- @machine.env.ui.info(data.chomp, :color => color, :prefix => false)
46
+ @machine.ui.info(
47
+ data,
48
+ :color => color, :new_line => false, :prefix => false)
49
49
  end
50
50
  end
51
51
 
@@ -10,35 +10,28 @@ if Vagrant::VERSION < "1.1.0"
10
10
  raise "The Vagrant Windows plugin is only compatible with Vagrant 1.1+"
11
11
  end
12
12
 
13
- # Add vagrant-windows plugin errors
14
- require "vagrant-windows/errors"
15
-
16
- # Add Vagrant WinRM communication channel
17
- require "vagrant-windows/communication/winrmcommunicator"
13
+ if Vagrant::VERSION >= "1.2.0"
14
+ # Monkey Patch the virtualbox share_folders action to make valid share names on windows
15
+ require_relative "monkey_patches/plugins/providers/virtualbox/action/share_folders"
16
+ end
18
17
 
19
- # Monkey patch the vbox42 driver
20
- require "vagrant-windows/monkey_patches/vbox_42_driver"
18
+ # Monkey patch the vbox42 driver to support read mac addresses
19
+ require_relative "monkey_patches/plugins/providers/virtualbox/driver/version_4_2"
21
20
 
22
21
  # Monkey Patch the VM object to support multiple channels, i.e. WinRM
23
- require "vagrant-windows/monkey_patches/machine"
22
+ require_relative "monkey_patches/lib/vagrant/machine"
24
23
 
25
- # Monkey patch the Puppet provisioner to support PowerShell/Windows
26
- require "vagrant-windows/monkey_patches/puppet"
24
+ # Monkey patch the Puppet provisioners to support PowerShell/Windows
25
+ require_relative "monkey_patches/plugins/provisioners/puppet/provisioner/puppet"
26
+ require_relative "monkey_patches/plugins/provisioners/puppet/provisioner/puppet_server"
27
27
 
28
- # Monkey patch the Chef-Solo provisioner to support PowerShell/Windows
29
- require "vagrant-windows/monkey_patches/chef_solo"
28
+ # Monkey patch the Chef provisioners to support PowerShell/Windows
29
+ require_relative "monkey_patches/plugins/provisioners/chef/provisioner/chef_solo"
30
+ require_relative "monkey_patches/plugins/provisioners/chef/provisioner/chef_client"
30
31
 
31
32
  # Monkey patch the shell provisioner to support PowerShell/batch/exe/Windows/etc
32
- require "vagrant-windows/monkey_patches/provisioner"
33
-
34
- # Add our windows specific config object
35
- require "vagrant-windows/config/windows"
36
-
37
- # Add our winrm specific config object
38
- require "vagrant-windows/config/winrm"
33
+ require_relative "monkey_patches/plugins/provisioners/shell/provisioner"
39
34
 
40
- # Add the new Vagrant Windows guest
41
- require "vagrant-windows/guest/windows"
42
35
 
43
36
  module VagrantWindows
44
37
  class Plugin < Vagrant.plugin("2")
@@ -47,19 +40,53 @@ module VagrantWindows
47
40
  This plugin installs a provider that allows Vagrant to manage
48
41
  Windows machines as guests.
49
42
  DESC
50
-
51
- guest(:windows) do
52
- VagrantWindows::Guest::Windows
53
- end
54
-
43
+
55
44
  config(:windows) do
45
+ require_relative "config/windows"
56
46
  VagrantWindows::Config::Windows
57
47
  end
58
-
48
+
59
49
  config(:winrm) do
50
+ require_relative "config/winrm"
60
51
  VagrantWindows::Config::WinRM
61
52
  end
53
+
54
+ guest(:windows) do
55
+ require_relative "guest/windows"
56
+ VagrantWindows::Guest::Windows
57
+ end
58
+
59
+ # Vagrant 1.2 introduced the concept of capabilities instead of implementing
60
+ # an interface on the guest.
61
+ if Vagrant::VERSION >= "1.2.0"
62
+
63
+ guest_capability(:windows, :change_host_name) do
64
+ require_relative "guest/cap/change_host_name"
65
+ VagrantWindows::Guest::Cap::ChangeHostName
66
+ end
67
+
68
+ guest_capability(:windows, :configure_networks) do
69
+ require_relative "guest/cap/configure_networks"
70
+ VagrantWindows::Guest::Cap::ConfigureNetworks
71
+ end
72
+
73
+ guest_capability(:windows, :halt) do
74
+ require_relative "guest/cap/halt"
75
+ VagrantWindows::Guest::Cap::Halt
76
+ end
77
+
78
+ guest_capability(:windows, :mount_virtualbox_shared_folder) do
79
+ require_relative "guest/cap/mount_virtualbox_shared_folder"
80
+ VagrantWindows::Guest::Cap::MountVirtualBoxSharedFolder
81
+ end
82
+
83
+ guest_capability(:windows, :mount_vmware_shared_folder) do
84
+ require_relative "guest/cap/mount_vmware_shared_folder"
85
+ VagrantWindows::Guest::Cap::MountVMwareSharedFolder
86
+ end
62
87
 
88
+ end
89
+
63
90
  # This initializes the internationalization strings.
64
91
  def self.setup_i18n
65
92
  I18n.load_path << File.expand_path("locales/en.yml", VagrantWindows.vagrant_windows_root)
@@ -0,0 +1,47 @@
1
+ schtasks /query /tn "chef-solo" | Out-Null
2
+ if ($?) {
3
+ # task already exists, kill it
4
+ schtasks /delete /tn "chef-solo" /f | Out-Null
5
+ }
6
+
7
+ # Ensure the chef task running file doesn't exist from a previous failure
8
+ if (Test-Path "<%= options[:chef_task_running] %>") {
9
+ del "<%= options[:chef_task_running] %>"
10
+ }
11
+
12
+ # schedule the task to run once in the far distant future
13
+ schtasks /create /tn "chef-solo" /xml "<%= options[:chef_task_xml] %>" /ru "<%= options[:user] %>" /rp "<%= options[:pass] %>" | Out-Null
14
+
15
+ # start the scheduled task right now
16
+ schtasks /run /tn "chef-solo" | Out-Null
17
+
18
+ # wait for run_chef.ps1 to start or timeout after 1 minute
19
+ $timeoutSeconds = 60
20
+ $elapsedSeconds = 0
21
+ while ( (!(Test-Path "<%= options[:chef_task_running] %>")) -and ($elapsedSeconds -lt $timeoutSeconds) ) {
22
+ Start-Sleep -s 1
23
+ $elapsedSeconds++
24
+ }
25
+
26
+ if ($elapsedSeconds -ge $timeoutSeconds) {
27
+ Write-Error "Timed out waiting for chef scheduled task to start"
28
+ exit -2
29
+ }
30
+
31
+ # read the entire file, but only write out new lines we haven't seen before
32
+ $numLinesRead = 0
33
+ $success = $TRUE
34
+ while (Test-Path "<%= options[:chef_task_running] %>") {
35
+ Start-Sleep -m 100
36
+
37
+ $text = (get-content "<%= options[:chef_stdout_log] %>")
38
+ $numLines = ($text | Measure-Object -line).lines
39
+ $numLinesToRead = $numLines - $numLinesRead
40
+
41
+ $text | select -first $numLinesToRead -skip $numLinesRead | ForEach {
42
+ Write-Host "$_"
43
+ }
44
+ $numLinesRead += $numLinesToRead
45
+ }
46
+
47
+ exit Get-Content "<%= options[:chef_task_exitcode] %>"
@@ -0,0 +1,45 @@
1
+ <?xml version="1.0" encoding="UTF-16"?>
2
+ <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
3
+ <RegistrationInfo>
4
+ <Date>2013-06-21T22:41:43</Date>
5
+ <Author>Administrator</Author>
6
+ </RegistrationInfo>
7
+ <Triggers>
8
+ <TimeTrigger>
9
+ <StartBoundary>2045-01-01T12:00:00</StartBoundary>
10
+ <Enabled>true</Enabled>
11
+ </TimeTrigger>
12
+ </Triggers>
13
+ <Principals>
14
+ <Principal id="Author">
15
+ <UserId>vagrant</UserId>
16
+ <LogonType>Password</LogonType>
17
+ <RunLevel>HighestAvailable</RunLevel>
18
+ </Principal>
19
+ </Principals>
20
+ <Settings>
21
+ <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
22
+ <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
23
+ <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
24
+ <AllowHardTerminate>true</AllowHardTerminate>
25
+ <StartWhenAvailable>false</StartWhenAvailable>
26
+ <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
27
+ <IdleSettings>
28
+ <StopOnIdleEnd>true</StopOnIdleEnd>
29
+ <RestartOnIdle>false</RestartOnIdle>
30
+ </IdleSettings>
31
+ <AllowStartOnDemand>true</AllowStartOnDemand>
32
+ <Enabled>true</Enabled>
33
+ <Hidden>false</Hidden>
34
+ <RunOnlyIfIdle>false</RunOnlyIfIdle>
35
+ <WakeToRun>false</WakeToRun>
36
+ <ExecutionTimeLimit>PT2H</ExecutionTimeLimit>
37
+ <Priority>7</Priority>
38
+ </Settings>
39
+ <Actions Context="Author">
40
+ <Exec>
41
+ <Command>powershell</Command>
42
+ <Arguments>-file <%= options[:chef_task_run_ps1] %></Arguments>
43
+ </Exec>
44
+ </Actions>
45
+ </Task>