Skip to content

Commit a9b43f2

Browse files
committed
[TEST] add windows vagrant boxes
Vagrant boxes now include options for windows server 2012r2 and server 2016. Since licensing prevents us from providing windows images, they're only configured in vagrant if passed via environment variables. The windows boxes aren't used in gradle's packaging tests yet. For elastic#26741
1 parent 13083e2 commit a9b43f2

File tree

2 files changed

+158
-4
lines changed

2 files changed

+158
-4
lines changed

TESTING.asciidoc

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,9 +363,17 @@ quality boxes available in vagrant atlas:
363363

364364
* sles-11
365365

366-
We're missing the following because our tests are very linux/bash centric:
366+
Windows boxes currently supported by the Vagrantfile (but not used in packaging
367+
tests yet) are
367368

368-
* Windows Server 2012
369+
* windows-2012r2 for Windows Server 2012 R2
370+
* windows-2016 for Windows Server 2016
371+
372+
Unfortunately, licensing issues prevent us from providing Windows boxes for
373+
public use. You can provide your own by setting the environment variables
374+
`VAGRANT_WINDOWS_2012R2_BOX` and/or `VAGRANT_WINDOWS_2016_BOX` with IDs of
375+
images that support remote connections through WinRM and remote Powershell
376+
sessions.
369377

370378
It's important to think of VMs like cattle. If they become lame you just shoot
371379
them and let vagrant reprovision them. Say you've hosed your precise VM:

Vagrantfile

Lines changed: 148 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,15 @@ Vagrant.configure(2) do |config|
3333
vbox.cpus = Integer(ENV['VAGRANT_CPUS'] || 4)
3434
end
3535

36+
# Vagrant and ruby stdlib expand '.' differently, so look for the build
37+
# in the directory containing the Vagrantfile
38+
vagrantfile_dir = File.expand_path('..', __FILE__)
39+
3640
# Switch the default share for the project root from /vagrant to
3741
# /elasticsearch because /vagrant is confusing when there is a project inside
3842
# the elasticsearch project called vagrant....
39-
config.vm.synced_folder '.', '/vagrant', disabled: true
40-
config.vm.synced_folder '.', '/elasticsearch'
43+
config.vm.synced_folder vagrantfile_dir, '/vagrant', disabled: true
44+
config.vm.synced_folder vagrantfile_dir, '/elasticsearch'
4145

4246
# Expose project directory. Note that VAGRANT_CWD may not be the same as Dir.pwd
4347
PROJECT_DIR = ENV['VAGRANT_PROJECT_DIR'] || Dir.pwd
@@ -121,6 +125,30 @@ Vagrant.configure(2) do |config|
121125
sles_common config, box
122126
end
123127
end
128+
129+
windows_2012r2_box = ENV['VAGRANT_WINDOWS_2012R2_BOX']
130+
if windows_2012r2_box && windows_2012r2_box.empty? == false
131+
'windows-2012r2'.tap do |box|
132+
config.vm.define box, define_opts do |config|
133+
config.vm.box = windows_2012r2_box
134+
windows_common config, box
135+
end
136+
end
137+
end
138+
139+
windows_2016_box = ENV['VAGRANT_WINDOWS_2016_BOX']
140+
if windows_2016_box && windows_2016_box.empty? == false
141+
'windows-2016'.tap do |box|
142+
config.vm.define box, define_opts do |config|
143+
config.vm.box = windows_2016_box
144+
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
145+
config.vm.provision 'enable long paths', type: 'shell', inline: <<-SHELL
146+
Set-ItemProperty -Path "HKLM:/SYSTEM/CurrentControlSet/Control/Filesystem/" -Name "LongPathsEnabled" -Value 1
147+
SHELL
148+
windows_common config, box
149+
end
150+
end
151+
end
124152
end
125153

126154
def deb_common(config, name, extra: '')
@@ -351,3 +379,121 @@ SUDOERS_VARS
351379
chmod 0440 /etc/sudoers.d/elasticsearch_vars
352380
SHELL
353381
end
382+
383+
def windows_common(config, name)
384+
config.vm.provision 'markerfile', type: 'shell', inline: <<-SHELL
385+
$ErrorActionPreference = "Stop"
386+
New-Item C:/is_vagrant_vm -ItemType file -Force | Out-Null
387+
SHELL
388+
389+
config.vm.provision 'clean es installs in tmp', run: 'always', type: 'shell', inline: <<-SHELL
390+
Remove-Item -Recurse -Force C:\\tmp\\elasticsearch*
391+
SHELL
392+
393+
config.vm.provision 'set prompt', type: 'shell', inline: <<-SHELL
394+
$ErrorActionPreference = "Stop"
395+
$ps_prompt = 'function Prompt { "#{name}:$($ExecutionContext.SessionState.Path.CurrentLocation)>" }'
396+
$ps_prompt | Out-File $PsHome/Microsoft.PowerShell_profile.ps1
397+
SHELL
398+
399+
# Windows' system APIs limit paths to 260 characters. In server 2016 we can raise this limit,
400+
# (see LongPathsEnabled above) but not in server 2012r2. This adds a powershell module that has basic
401+
# copy and delete command that can handle long paths
402+
config.vm.provision 'long path shim module', type: 'shell' do |s|
403+
s.privileged = false
404+
s.inline = <<-SHELL
405+
$ErrorActionPreference = "Stop"
406+
$longPathScript = @'
407+
#{powershell_long_path_module}
408+
'@
409+
$ModuleDir = "C:/Users/vagrant/Documents/WindowsPowerShell/Modules/LongPathShims"
410+
$ModuleFile = "$ModuleDir/LongPathShims.psm1"
411+
if (-Not (Test-Path "$ModuleDir")) {
412+
New-Item "$ModuleDir" -ItemType Directory | Out-Null
413+
}
414+
$longPathScript | Out-File "$ModuleFile"
415+
SHELL
416+
end
417+
418+
powershell_install_deps config
419+
end
420+
421+
# Powershell's filesystem commands cannot handle long paths by default. This module implements
422+
# the required commands by calling Robocopy [1], a Windows system utility for moving files around
423+
# that can handle long paths by default. Robocopy returns unusual exit codes [2] so we call it in
424+
# a wrapper that converts them to what we'd normally expect.
425+
#
426+
# The Remove-Long-Path function works by syncing the contents of an empty directory to the
427+
# delete target, which has the effect of recursively deleting it.
428+
#
429+
# [1] https://ss64.com/nt/robocopy.html
430+
# [2] https://ss64.com/nt/robocopy-exit.html
431+
def powershell_long_path_module
432+
<<-SHELL
433+
function Copy-Long-Path {
434+
param(
435+
[string]$Source,
436+
[string]$Destination
437+
)
438+
439+
robocopy "$Source" "$Destination" /E /COPY:DT /DCOPY:T /NFL /NDL /NJH /NJS /NC /NS /NP
440+
Handle-Robocopy-Exit-Code $LASTEXITCODE
441+
}
442+
443+
function Remove-Long-Path {
444+
param(
445+
[string]$Target
446+
)
447+
448+
$EmptyDir = "C:\\intentionally_empty"
449+
450+
try {
451+
New-Item "$EmptyDir" -ItemType Directory | Out-Null
452+
# There doesn't appear to be a way to silence output about files that are purged,
453+
# so just sent it to null as writing it to the terminal is very slow
454+
robocopy "$EmptyDir" "$Target" /PURGE /NFL /NDL /NJH /NJS /NC /NS /NP | Out-Null
455+
$RobocopyExitCode = $LASTEXITCODE
456+
Remove-Item "$Target" -Recurse
457+
Handle-Robocopy-Exit-Code $RobocopyExitCode
458+
} finally {
459+
Remove-Item "$EmptyDir" -Recurse
460+
}
461+
}
462+
463+
function Handle-Robocopy-Exit-Code {
464+
param(
465+
[int]$ExitCode
466+
)
467+
468+
Write-Verbose "robocopy returned exit code $ExitCode"
469+
if ($ExitCode -ge 7) {
470+
Write-Error "robocopy encountered an error and returned exit code $ExitCode"
471+
}
472+
}
473+
SHELL
474+
end
475+
476+
# Just check that java is installed - when other dependencies are needed
477+
# in the future, this is where they'll go
478+
def powershell_install_deps(config)
479+
config.vm.provision 'install deps', type: 'shell', inline: <<-SHELL
480+
$ErrorActionPreference = "Stop"
481+
482+
function Installed {
483+
Param(
484+
[string]$command
485+
)
486+
487+
try {
488+
Get-Command $command
489+
return $true
490+
} catch {
491+
return $false
492+
}
493+
}
494+
495+
if (-Not (Installed java)) {
496+
Write-Error "java is not installed"
497+
}
498+
SHELL
499+
end

0 commit comments

Comments
 (0)