vagrant-windows 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +19 -0
- data/Gemfile +5 -0
- data/README.md +78 -0
- data/Rakefile +2 -0
- data/lib/vagrant-windows/communication/winrm.rb +180 -0
- data/lib/vagrant-windows/config/windows.rb +27 -0
- data/lib/vagrant-windows/config/winrm.rb +31 -0
- data/lib/vagrant-windows/errors.rb +17 -0
- data/lib/vagrant-windows/guest/windows.rb +54 -0
- data/lib/vagrant-windows/monkey_patches/vm.rb +16 -0
- data/lib/vagrant-windows/scripts/command_alias.ps1 +23 -0
- data/lib/vagrant-windows/scripts/mount_volume.ps1.erb +43 -0
- data/lib/vagrant-windows/version.rb +3 -0
- data/lib/vagrant-windows/winrm.rb +82 -0
- data/lib/vagrant_init.rb +18 -0
- data/vagrant-windows.gemspec +21 -0
- metadata +111 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
Building a Base Box
|
2
|
+
===================
|
3
|
+
|
4
|
+
-Enable WinRM
|
5
|
+
|
6
|
+
```
|
7
|
+
winrm quickconfig -q
|
8
|
+
winrm set winrm/config/winrs @{MaxMemoryPerShellMB="512"}
|
9
|
+
winrm set winrm/config @{MaxTimeoutms="1800000"}
|
10
|
+
winrm set winrm/config/service @{AllowUnencrypted="true"}
|
11
|
+
winrm set winrm/config/service/auth @{Basic="true"}
|
12
|
+
```
|
13
|
+
- Create a vagrant user
|
14
|
+
- For things to work out of the box, username and password should both be vagrant
|
15
|
+
|
16
|
+
- Turn off UAC
|
17
|
+
- Disable Shutdown Tracker
|
18
|
+
|
19
|
+
The Vagrant File
|
20
|
+
================
|
21
|
+
|
22
|
+
Add the following to your Vagrantfile
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
config.vm.guest = :windows
|
26
|
+
|
27
|
+
config.vm.forward_port 3389, 3390, :name => "rdp", :auto => true
|
28
|
+
config.vm.forward_port 5985, 5985, :name => "winrm", :auto => true
|
29
|
+
```
|
30
|
+
|
31
|
+
Example:
|
32
|
+
```ruby
|
33
|
+
Vagrant::Config.run do |config|
|
34
|
+
|
35
|
+
# Configure base box parameters
|
36
|
+
config.vm.box = "windows2008r2"
|
37
|
+
config.vm.box_url = "./windows-2008-r2.box"
|
38
|
+
config.vm.guest = :windows
|
39
|
+
|
40
|
+
config.vm.forward_port 3389, 3390, :name => "rdp", :auto => true
|
41
|
+
config.vm.forward_port 5985, 5985, :name => "winrm", :auto => true
|
42
|
+
|
43
|
+
config.vm.provision :chef_solo do |chef|
|
44
|
+
chef.add_recipe("your::recipe")
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
What Works?
|
50
|
+
===========
|
51
|
+
- vagrant up|hault|reload|provision
|
52
|
+
- Chef Vagrant Provisioner
|
53
|
+
|
54
|
+
What has not been tested
|
55
|
+
========================
|
56
|
+
- Everything Else!!!
|
57
|
+
- Shell and Puppet Provisioners
|
58
|
+
- Shell should work, though I have not vetted it yet.
|
59
|
+
|
60
|
+
What Can I do to help?
|
61
|
+
======================
|
62
|
+
1. Contribute Code (See Below)
|
63
|
+
2. Test Various Scenarios and file bugs for things that dont work
|
64
|
+
|
65
|
+
Contributing
|
66
|
+
============
|
67
|
+
1. Fork it.
|
68
|
+
2. Create a branch (git checkout -b my_feature_branch)
|
69
|
+
3. Commit your changes (git commit -am "Added a sweet feature")
|
70
|
+
4. Push to the branch (git push origin my_feature_branch)
|
71
|
+
5. Create a pull requst from your branch into master (Please be sure to provide enough detail for us to cipher what this change is doing)
|
72
|
+
|
73
|
+
|
74
|
+
References and Shout Outs
|
75
|
+
=========================
|
76
|
+
Chris McClimans - Vagrant Branch (https://github.com/hh/vagrant/blob/feature/winrm/)
|
77
|
+
Dan Wanek - WinRM GEM (https://github.com/zenchild/WinRM)
|
78
|
+
+1 For being super responsive to pull requests.
|
data/Rakefile
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
|
3
|
+
require 'log4r'
|
4
|
+
#require 'em-winrm'
|
5
|
+
require 'winrm'
|
6
|
+
require 'highline'
|
7
|
+
|
8
|
+
require 'vagrant/util/ansi_escape_code_remover'
|
9
|
+
require 'vagrant/util/file_mode'
|
10
|
+
require 'vagrant/util/platform'
|
11
|
+
require 'vagrant/util/retryable'
|
12
|
+
|
13
|
+
module Vagrant
|
14
|
+
module Communication
|
15
|
+
# Provides communication with the VM via WinRM.
|
16
|
+
class WinRM < Base
|
17
|
+
|
18
|
+
include Util::ANSIEscapeCodeRemover
|
19
|
+
include Util::Retryable
|
20
|
+
|
21
|
+
attr_reader :logger
|
22
|
+
attr_reader :vm
|
23
|
+
|
24
|
+
def initialize(vm)
|
25
|
+
@vm = vm
|
26
|
+
@logger = Log4r::Logger.new("vagrant::communication::winrm")
|
27
|
+
@co = nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def ready?
|
31
|
+
logger.debug("Checking whether WinRM is ready...")
|
32
|
+
|
33
|
+
Timeout.timeout(@vm.config.winrm.timeout) do
|
34
|
+
execute "hostname"
|
35
|
+
end
|
36
|
+
|
37
|
+
# If we reached this point then we successfully connected
|
38
|
+
logger.info("WinRM is ready!")
|
39
|
+
true
|
40
|
+
rescue Timeout::Error => e
|
41
|
+
#, Errors::SSHConnectionRefused, Net::SSH::Disconnect => e
|
42
|
+
# The above errors represent various reasons that WinRM may not be
|
43
|
+
# ready yet. Return false.
|
44
|
+
logger.info("WinRM not up yet: #{e.inspect}")
|
45
|
+
|
46
|
+
return false
|
47
|
+
end
|
48
|
+
|
49
|
+
# Wrap Sudo in execute.... One day we could integrate with UAC, but Icky
|
50
|
+
def sudo(command, opts=nil, &block)
|
51
|
+
execute(command,opts,&block)
|
52
|
+
end
|
53
|
+
|
54
|
+
def execute(command, opts=nil, &block)
|
55
|
+
|
56
|
+
# Connect to WinRM, giving it a few tries
|
57
|
+
logger.info("Connecting to WinRM: #{@vm.winrm.info[:host]}:#{@vm.winrm.info[:port]}")
|
58
|
+
|
59
|
+
opts = {
|
60
|
+
:error_check => true,
|
61
|
+
:error_class => Errors::VagrantError,
|
62
|
+
:error_key => :winrm_bad_exit_status,
|
63
|
+
:command => command,
|
64
|
+
:sudo => false,
|
65
|
+
:shell => :powershell
|
66
|
+
}.merge(opts || {})
|
67
|
+
|
68
|
+
# Connect via WinRM and execute the command in the shell.
|
69
|
+
exceptions = [HTTPClient::KeepAliveDisconnected]
|
70
|
+
exit_status = retryable(:tries => @vm.config.winrm.max_tries, :on => exceptions, :sleep => 10) do
|
71
|
+
logger.debug "WinRM Trying to connect"
|
72
|
+
shell_execute(command,opts[:shell], &block)
|
73
|
+
end
|
74
|
+
|
75
|
+
logger.debug("#{command} EXIT STATUS #{exit_status.inspect}")
|
76
|
+
|
77
|
+
# Check for any errors
|
78
|
+
if opts[:error_check] && exit_status != 0
|
79
|
+
# The error classes expect the translation key to be _key,
|
80
|
+
# but that makes for an ugly configuration parameter, so we
|
81
|
+
# set it here from `error_key`
|
82
|
+
error_opts = opts.merge(:_key => opts[:error_key])
|
83
|
+
raise opts[:error_class], error_opts
|
84
|
+
end
|
85
|
+
|
86
|
+
# Return the exit status
|
87
|
+
exit_status
|
88
|
+
end
|
89
|
+
|
90
|
+
def new_session
|
91
|
+
opts = {
|
92
|
+
:user => vm.config.winrm.username,
|
93
|
+
:pass => vm.config.winrm.password,
|
94
|
+
:host => vm.config.winrm.host,
|
95
|
+
:port => vm.winrm.info[:port],
|
96
|
+
:basic_auth_only => true
|
97
|
+
}.merge ({})
|
98
|
+
|
99
|
+
# create a session
|
100
|
+
begin
|
101
|
+
endpoint = "http://#{opts[:host]}:#{opts[:port]}/wsman"
|
102
|
+
client = ::WinRM::WinRMWebService.new(endpoint, :plaintext, opts)
|
103
|
+
client.set_timeout(opts[:operation_timeout]) if opts[:operation_timeout]
|
104
|
+
rescue ::WinRM::WinRMAuthorizationError => error
|
105
|
+
raise ::WinRM::WinRMAuthorizationError.new("#{error.message}@#{opts[:host]}")
|
106
|
+
end
|
107
|
+
|
108
|
+
client
|
109
|
+
end
|
110
|
+
|
111
|
+
def session
|
112
|
+
@session ||= new_session
|
113
|
+
end
|
114
|
+
|
115
|
+
def h
|
116
|
+
@highline ||= HighLine.new
|
117
|
+
end
|
118
|
+
|
119
|
+
def print_data(data, color = :cyan)
|
120
|
+
if data =~ /\n/
|
121
|
+
data.split(/\n/).each { |d| print_data(d, color) }
|
122
|
+
else
|
123
|
+
puts "#{h.color('winrm', color)} #{data.chomp}"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def upload(from, to)
|
128
|
+
file = "winrm-upload-#{rand()}"
|
129
|
+
file_name = (session.cmd("echo %TEMP%\\#{file}"))[:data][0][:stdout].chomp
|
130
|
+
session.powershell <<-EOH
|
131
|
+
if(Test-Path #{to})
|
132
|
+
{
|
133
|
+
rm #{to}
|
134
|
+
}
|
135
|
+
EOH
|
136
|
+
Base64.encode64(IO.binread(from)).gsub("\n",'').chars.to_a.each_slice(8000-file_name.size) do |chunk|
|
137
|
+
out = session.cmd( "echo #{chunk.join} >> \"#{file_name}\"" )
|
138
|
+
end
|
139
|
+
execute "mkdir [System.IO.Path]::GetDirectoryName(\"#{to}\")"
|
140
|
+
execute <<-EOH
|
141
|
+
$base64_string = Get-Content \"#{file_name}\"
|
142
|
+
$bytes = [System.Convert]::FromBase64String($base64_string)
|
143
|
+
$new_file = [System.IO.Path]::GetFullPath(\"#{to}\")
|
144
|
+
[System.IO.File]::WriteAllBytes($new_file,$bytes)
|
145
|
+
EOH
|
146
|
+
end
|
147
|
+
|
148
|
+
protected
|
149
|
+
|
150
|
+
# Executes the command on an SSH connection within a login shell.
|
151
|
+
def shell_execute(command,shell = :powershell)
|
152
|
+
logger.info("Execute: #{command}")
|
153
|
+
exit_status = nil
|
154
|
+
|
155
|
+
if shell.eql? :cmd
|
156
|
+
output = session.cmd(command) do |out,error|
|
157
|
+
print_data(out) if out
|
158
|
+
print_data(error) if error
|
159
|
+
end
|
160
|
+
elsif shell.eql? :powershell
|
161
|
+
new_command = File.read(File.expand_path("#{File.dirname(__FILE__)}/../scripts/command_alias.ps1"))
|
162
|
+
new_command << "\r\n"
|
163
|
+
new_command << command
|
164
|
+
output = session.powershell(new_command) do |out,error|
|
165
|
+
print_data(out) if out
|
166
|
+
print_data(error) if error
|
167
|
+
end
|
168
|
+
else
|
169
|
+
raise Vagrant::Errors::WinRMInvalidShell, "#{shell} is not a valid type of shell"
|
170
|
+
end
|
171
|
+
|
172
|
+
exit_status = output[:exitcode]
|
173
|
+
logger.debug exit_status.inspect
|
174
|
+
|
175
|
+
# Return the final exit status
|
176
|
+
return exit_status
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Vagrant
|
2
|
+
module Config
|
3
|
+
class Windows < Vagrant::Config::Base
|
4
|
+
attr_accessor :winrm_user
|
5
|
+
attr_accessor :winrm_password
|
6
|
+
attr_accessor :halt_timeout
|
7
|
+
attr_accessor :halt_check_interval
|
8
|
+
attr_accessor :device
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@winrm_user = 'vagrant'
|
12
|
+
@winrm_password = 'vagrant'
|
13
|
+
@halt_timeout = 30
|
14
|
+
@halt_check_interval = 1
|
15
|
+
@device = "e1000g"
|
16
|
+
end
|
17
|
+
|
18
|
+
def validate(env, errors)
|
19
|
+
[ :winrm_user, :winrm_password].each do |field|
|
20
|
+
errors.add(I18n.t("vagrant.config.common.error_empty", :field => field)) if !instance_variable_get("@#{field}".to_sym)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
Vagrant.config_keys.register(:windows) { Vagrant::Config::Windows }
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Vagrant
|
2
|
+
module Config
|
3
|
+
class WinRM < Vagrant::Config::Base
|
4
|
+
attr_accessor :username
|
5
|
+
attr_accessor :password
|
6
|
+
attr_accessor :host
|
7
|
+
attr_accessor :port
|
8
|
+
attr_accessor :guest_port
|
9
|
+
attr_accessor :max_tries
|
10
|
+
attr_accessor :timeout
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@username = "vagrant"
|
14
|
+
@password = "vagrant"
|
15
|
+
@guest_port = 5985
|
16
|
+
@host = "localhost"
|
17
|
+
@max_tries = 12
|
18
|
+
@timeout = 30
|
19
|
+
end
|
20
|
+
|
21
|
+
def validate(env, errors)
|
22
|
+
[:username, :password, :host, :max_tries, :timeout].each do |field|
|
23
|
+
errors.add(I18n.t("vagrant.config.common.error_empty", :field => field)) if !instance_variable_get("@#{field}".to_sym)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Vagrant.config_keys.register(:winrm) { Vagrant::Config::WinRM }
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Vagrant
|
2
|
+
module Errors
|
3
|
+
class WinRMPortNotDetected < VagrantError
|
4
|
+
status_code(550)
|
5
|
+
error_key(:winrm_port_not_detected)
|
6
|
+
end
|
7
|
+
|
8
|
+
class WinRMInvalidShell < VagrantError
|
9
|
+
status_code(551)
|
10
|
+
error_key(:winrm_invalid_shell)
|
11
|
+
end
|
12
|
+
class WinRMTransferError < VagrantError
|
13
|
+
status_code(552)
|
14
|
+
error_key(:winrm_upload_error)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Vagrant
|
2
|
+
module Guest
|
3
|
+
# A general Vagrant system implementation for "windows".
|
4
|
+
#
|
5
|
+
# Contributed by Chris McClimans <chris@hippiehacker.org>
|
6
|
+
class Windows < Base
|
7
|
+
# A custom config class which will be made accessible via `config.windows`
|
8
|
+
# Here for whenever it may be used.
|
9
|
+
class WindowsError < Errors::VagrantError
|
10
|
+
error_namespace("vagrant.guest.windows")
|
11
|
+
end
|
12
|
+
|
13
|
+
def change_host_name(name)
|
14
|
+
#### on windows, renaming a computer seems to require a reboot
|
15
|
+
vm.channel.execute("wmic computersystem where name=\"%COMPUTERNAME%\" call rename name=\"#{name}\"")
|
16
|
+
end
|
17
|
+
|
18
|
+
def halt
|
19
|
+
@vm.channel.execute("shutdown /s /t 1 /c \"Vagrant Halt\" /f /d p:4:1")
|
20
|
+
|
21
|
+
# Wait until the VM's state is actually powered off. If this doesn't
|
22
|
+
# occur within a reasonable amount of time (15 seconds by default),
|
23
|
+
# then simply return and allow Vagrant to kill the machine.
|
24
|
+
count = 0
|
25
|
+
while @vm.state != :poweroff
|
26
|
+
count += 1
|
27
|
+
|
28
|
+
return if count >= @vm.config.linux.halt_timeout
|
29
|
+
sleep @vm.config.windows.halt_check_interval
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def mount_shared_folder(name, guestpath, options)
|
34
|
+
mount_script = TemplateRenderer.render(File.expand_path("#{File.dirname(__FILE__)}/../scripts/mount_volume.ps1"),
|
35
|
+
:options => {:mount_point => guestpath, :name => name})
|
36
|
+
|
37
|
+
@vm.channel.execute(mount_script,{:shell => :powershell})
|
38
|
+
end
|
39
|
+
|
40
|
+
def windows_path(path)
|
41
|
+
p = ''
|
42
|
+
if path =~ /^\//
|
43
|
+
p << 'C:\\'
|
44
|
+
end
|
45
|
+
p << path
|
46
|
+
p.gsub! /\//, "\\"
|
47
|
+
p.gsub /\\\\{0,}/, "\\"
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
Vagrant.guests.register(:windows) { Vagrant::Guest::Windows }
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Vagrant
|
2
|
+
class VM
|
3
|
+
def winrm
|
4
|
+
@winrm ||= WinRM.new(self)
|
5
|
+
end
|
6
|
+
|
7
|
+
def channel
|
8
|
+
if @guest.class.eql? Vagrant::Guest::Windows
|
9
|
+
@channel ||= Communication::WinRM.new(self)
|
10
|
+
else
|
11
|
+
@channel ||= Communication::SSH.new(self)
|
12
|
+
end
|
13
|
+
@channel
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
function which {
|
2
|
+
$command = [Array](Get-Command $args[0] -errorAction continue)
|
3
|
+
write-host $command[0].Definition
|
4
|
+
}
|
5
|
+
|
6
|
+
function test ([Switch] $d, [String] $path) {
|
7
|
+
Resolve-Path $path| Out-Null;
|
8
|
+
}
|
9
|
+
|
10
|
+
function chown {
|
11
|
+
exit 0
|
12
|
+
}
|
13
|
+
|
14
|
+
function mkdir ([Switch] $p, [String] $path)
|
15
|
+
{
|
16
|
+
if(Test-Path $path)
|
17
|
+
{
|
18
|
+
exit 0
|
19
|
+
} else {
|
20
|
+
New-Item $p -Type Directory -Force | Out-Null
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
function Test-ReparsePoint([string]$path) {
|
3
|
+
$file = Get-Item $path -Force -ea 0
|
4
|
+
return [bool]($file.Attributes -band [IO.FileAttributes]::ReparsePoint)
|
5
|
+
}
|
6
|
+
|
7
|
+
$MountPoint = [System.IO.Path]::GetFullPath("<%= options[:mount_point] %>")
|
8
|
+
$ShareName = "<%= options[:name] %>"
|
9
|
+
|
10
|
+
Write-Host "Attempting to mount $ShareName to $MountPoint"
|
11
|
+
if( (Test-Path "$MountPoint") -and (Test-ReparsePoint "$MountPoint") )
|
12
|
+
{
|
13
|
+
Write-Host "Junction already exists, so I will delete it"
|
14
|
+
# Powershell refuses to delete junctions, oh well use cmd
|
15
|
+
cmd /c rd "$MountPoint"
|
16
|
+
|
17
|
+
if ( $LASTEXITCODE -ne 0 )
|
18
|
+
{
|
19
|
+
Write-Error "Failed to delete symbolic link at $MountPoint"
|
20
|
+
exit 1
|
21
|
+
}
|
22
|
+
|
23
|
+
}
|
24
|
+
elseif(Test-Path $MountPoint)
|
25
|
+
{
|
26
|
+
Write-Host "Mount point already exists and is not a symbolic link"
|
27
|
+
exit 1
|
28
|
+
}
|
29
|
+
|
30
|
+
$BaseDirectory = [System.IO.Path]::GetDirectoryName($MountPoint)
|
31
|
+
|
32
|
+
if (-not (Test-Path $BaseDirectory))
|
33
|
+
{
|
34
|
+
Write-Host "Creating parent directory for mount point"
|
35
|
+
mkdir $BaseDirectory
|
36
|
+
}
|
37
|
+
|
38
|
+
cmd /c mklink /D "$MountPoint" "\\vboxsrv\$ShareName"
|
39
|
+
|
40
|
+
if ( $LASTEXITCODE -ne 0 )
|
41
|
+
{
|
42
|
+
exit 1
|
43
|
+
}
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
#require 'em-winrm'
|
3
|
+
|
4
|
+
module Vagrant
|
5
|
+
# Manages WINRM access to a specific environment. Allows an environment to
|
6
|
+
# run commands, upload files, and check if a host is up.
|
7
|
+
class WinRM
|
8
|
+
include Util::SafeExec
|
9
|
+
|
10
|
+
def initialize(vm)
|
11
|
+
@vm = vm
|
12
|
+
@logger = Log4r::Logger.new("vagrant::winrm")
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns a hash of information necessary for accessing this
|
16
|
+
# virtual machine via WINRM.
|
17
|
+
#
|
18
|
+
# @return [Hash]
|
19
|
+
def info
|
20
|
+
results = {
|
21
|
+
:host => @vm.config.winrm.host,
|
22
|
+
:port => @vm.config.winrm.port || @vm.driver.ssh_port(@vm.config.winrm.guest_port),
|
23
|
+
:username => @vm.config.winrm.username
|
24
|
+
}
|
25
|
+
|
26
|
+
# This can happen if no port is set and for some reason Vagrant
|
27
|
+
# can't detect an SSH port.
|
28
|
+
raise Errors::WinRMPortNotDetected if !results[:port]
|
29
|
+
|
30
|
+
# Return the results
|
31
|
+
return results
|
32
|
+
end
|
33
|
+
|
34
|
+
# Checks if this environment's machine is up (i.e. responding to WINRM).
|
35
|
+
#
|
36
|
+
# @return [Boolean]
|
37
|
+
def up?
|
38
|
+
# We have to determine the port outside of the block since it uses
|
39
|
+
# API calls which can only be used from the main thread in JRuby on
|
40
|
+
# Windows
|
41
|
+
ssh_port = port
|
42
|
+
|
43
|
+
require 'timeout'
|
44
|
+
Timeout.timeout(@env.config.ssh.timeout) do
|
45
|
+
execute 'hostname'
|
46
|
+
end
|
47
|
+
|
48
|
+
true
|
49
|
+
rescue Timeout::Error, Errno::ECONNREFUSED
|
50
|
+
return false
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns the port which is either given in the options hash or taken from
|
54
|
+
# the config by finding it in the forwarded ports hash based on the
|
55
|
+
# `config.ssh.forwarded_port_key`.
|
56
|
+
def port(opts={})
|
57
|
+
# Check if port was specified in options hash
|
58
|
+
return opts[:port] if opts[:port]
|
59
|
+
|
60
|
+
# Check if a port was specified in the config
|
61
|
+
return @env.config.winrm.port if @env.config.winrm.port
|
62
|
+
|
63
|
+
# Check if we have an SSH forwarded port
|
64
|
+
pnum_by_name = nil
|
65
|
+
pnum_by_destination = nil
|
66
|
+
@logger.info("Looking for winrm port: #{opts}")
|
67
|
+
@logger.info("Looking for winrm port: #{env.config.winrm.inspect}")
|
68
|
+
|
69
|
+
env.vm.vm.network_adapters.each do |na|
|
70
|
+
# Look for the port number by destination...
|
71
|
+
pnum_by_destination = na.nat_driver.forwarded_ports.detect do |fp|
|
72
|
+
fp.guestport == env.config.winrm.guest_port
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
return pnum_by_destination.hostport if pnum_by_destination
|
77
|
+
|
78
|
+
# This should NEVER happen.
|
79
|
+
raise Errors::WinRMPortNotDetected
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/vagrant_init.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#Add Windows Guest Defintion
|
2
|
+
require 'vagrant-windows/guest/windows'
|
3
|
+
|
4
|
+
#Add Configuration Items
|
5
|
+
require 'vagrant-windows/config/windows'
|
6
|
+
require 'vagrant-windows/config/winrm'
|
7
|
+
|
8
|
+
# Add WinRM Communication Channel
|
9
|
+
require 'vagrant-windows/communication/winrm'
|
10
|
+
|
11
|
+
#Monkey Patch the VM object to support multiple channels
|
12
|
+
require 'vagrant-windows/monkey_patches/vm'
|
13
|
+
|
14
|
+
require 'vagrant-windows/winrm'
|
15
|
+
|
16
|
+
#Errors are good
|
17
|
+
require 'vagrant-windows/errors'
|
18
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/vagrant-windows/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Paul Morton"]
|
6
|
+
gem.email = ["pmorton@biaprotect.com"]
|
7
|
+
gem.description = %q{Windows Guest Support for Vagrant}
|
8
|
+
gem.summary = %q{A small gem that adds windows guest support to vagrant, uses WinRM as the Communication Channel}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "vagrant-windows"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = VagrantWindows::VERSION
|
17
|
+
|
18
|
+
gem.add_runtime_dependency "winrm", "~> 1.1.1"
|
19
|
+
gem.add_runtime_dependency 'vagrant', "~> 1.0.3"
|
20
|
+
gem.add_runtime_dependency 'highline'
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vagrant-windows
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Paul Morton
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-06-04 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: winrm
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.1.1
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.1.1
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: vagrant
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 1.0.3
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.0.3
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: highline
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: Windows Guest Support for Vagrant
|
63
|
+
email:
|
64
|
+
- pmorton@biaprotect.com
|
65
|
+
executables: []
|
66
|
+
extensions: []
|
67
|
+
extra_rdoc_files: []
|
68
|
+
files:
|
69
|
+
- .gitignore
|
70
|
+
- Gemfile
|
71
|
+
- Gemfile.lock
|
72
|
+
- README.md
|
73
|
+
- Rakefile
|
74
|
+
- lib/vagrant-windows/communication/winrm.rb
|
75
|
+
- lib/vagrant-windows/config/windows.rb
|
76
|
+
- lib/vagrant-windows/config/winrm.rb
|
77
|
+
- lib/vagrant-windows/errors.rb
|
78
|
+
- lib/vagrant-windows/guest/windows.rb
|
79
|
+
- lib/vagrant-windows/monkey_patches/vm.rb
|
80
|
+
- lib/vagrant-windows/scripts/command_alias.ps1
|
81
|
+
- lib/vagrant-windows/scripts/mount_volume.ps1.erb
|
82
|
+
- lib/vagrant-windows/version.rb
|
83
|
+
- lib/vagrant-windows/winrm.rb
|
84
|
+
- lib/vagrant_init.rb
|
85
|
+
- vagrant-windows.gemspec
|
86
|
+
homepage: ''
|
87
|
+
licenses: []
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
none: false
|
94
|
+
requirements:
|
95
|
+
- - ! '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ! '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
requirements: []
|
105
|
+
rubyforge_project:
|
106
|
+
rubygems_version: 1.8.24
|
107
|
+
signing_key:
|
108
|
+
specification_version: 3
|
109
|
+
summary: A small gem that adds windows guest support to vagrant, uses WinRM as the
|
110
|
+
Communication Channel
|
111
|
+
test_files: []
|