vagrant-windows-hyperv 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/Gemfile +15 -0
  4. data/LICENSE.txt +7 -0
  5. data/README.md +89 -0
  6. data/Rakefile +29 -0
  7. data/example_box/metadata.json +1 -0
  8. data/lib/vagrant-windows-hyperv.rb +38 -0
  9. data/lib/vagrant-windows-hyperv/action.rb +81 -0
  10. data/lib/vagrant-windows-hyperv/action/export.rb +54 -0
  11. data/lib/vagrant-windows-hyperv/action/package.rb +21 -0
  12. data/lib/vagrant-windows-hyperv/action/rdp.rb +49 -0
  13. data/lib/vagrant-windows-hyperv/action/setup_package_files.rb +55 -0
  14. data/lib/vagrant-windows-hyperv/command/rdp/command.rb +22 -0
  15. data/lib/vagrant-windows-hyperv/communication/powershell.rb +37 -0
  16. data/lib/vagrant-windows-hyperv/driver.rb +89 -0
  17. data/lib/vagrant-windows-hyperv/errors.rb +31 -0
  18. data/lib/vagrant-windows-hyperv/guest/cap/halt.rb +19 -0
  19. data/lib/vagrant-windows-hyperv/guest/windows.rb +25 -0
  20. data/lib/vagrant-windows-hyperv/monkey_patch/action/provision.rb +32 -0
  21. data/lib/vagrant-windows-hyperv/monkey_patch/machine.rb +22 -0
  22. data/lib/vagrant-windows-hyperv/monkey_patch/plugins/synced_folders/smb/synced_folders.rb +55 -0
  23. data/lib/vagrant-windows-hyperv/monkey_patch/util/powershell.rb +37 -0
  24. data/lib/vagrant-windows-hyperv/plugin.rb +85 -0
  25. data/lib/vagrant-windows-hyperv/provider.rb +30 -0
  26. data/lib/vagrant-windows-hyperv/provisioner/chef_solo.rb +181 -0
  27. data/lib/vagrant-windows-hyperv/provisioner/puppet.rb +99 -0
  28. data/lib/vagrant-windows-hyperv/provisioner/shell.rb +81 -0
  29. data/lib/vagrant-windows-hyperv/scripts/check_winrm.ps1 +41 -0
  30. data/lib/vagrant-windows-hyperv/scripts/export_vm.ps1 +31 -0
  31. data/lib/vagrant-windows-hyperv/scripts/file_sync.ps1 +145 -0
  32. data/lib/vagrant-windows-hyperv/scripts/host_info.ps1 +25 -0
  33. data/lib/vagrant-windows-hyperv/scripts/hyperv_manager.ps1 +36 -0
  34. data/lib/vagrant-windows-hyperv/scripts/run_in_remote.ps1 +31 -0
  35. data/lib/vagrant-windows-hyperv/scripts/upload_file.ps1 +95 -0
  36. data/lib/vagrant-windows-hyperv/scripts/utils/create_session.ps1 +34 -0
  37. data/lib/vagrant-windows-hyperv/scripts/utils/write_messages.ps1 +18 -0
  38. data/lib/vagrant-windows-hyperv/version.rb +10 -0
  39. data/locales/en.yml +15 -0
  40. data/spec/hyper-v/config_spec.rb +36 -0
  41. data/spec/hyper-v/spec_helper.rb +9 -0
  42. data/templates/provisioners/chef-solo/solo.erb +51 -0
  43. data/vagrant-windows-hyperv.gemspec +63 -0
  44. data/vagrantfile_examples/Vagrantfile_linux +23 -0
  45. data/vagrantfile_examples/Vagrantfile_windows +24 -0
  46. metadata +171 -0
@@ -0,0 +1,145 @@
1
+ #-------------------------------------------------------------------------
2
+ # Copyright (c) Microsoft Open Technologies, Inc.
3
+ # All Rights Reserved. Licensed under the Apache 2.0 License.
4
+ #--------------------------------------------------------------------------
5
+
6
+ param (
7
+ [string]$vm_id = $(throw "-vm_id is required."),
8
+ [string]$guest_ip = $(throw "-guest_ip is required."),
9
+ [string]$username = $(throw "-guest_username is required."),
10
+ [string]$password = $(throw "-guest_password is required."),
11
+ [string]$host_path = $(throw "-host_path is required."),
12
+ [string]$guest_path = $(throw "-guest_path is required.")
13
+ )
14
+
15
+ # Include the following modules
16
+ $presentDir = Split-Path -parent $PSCommandPath
17
+ $modules = @()
18
+ $modules += $presentDir + "\utils\write_messages.ps1"
19
+ $modules += $presentDir + "\utils\create_session.ps1"
20
+ forEach ($module in $modules) { . $module }
21
+
22
+ function Get-file-hash($source_path, $delimiter) {
23
+ $source_files = @()
24
+ (Get-ChildItem $source_path -rec -force | ForEach-Object -Process {
25
+ Get-FileHash -Path $_.FullName -Algorithm MD5 } ) |
26
+ ForEach-Object -Process {
27
+ $source_files += $_.Path.Replace($source_path, "") + $delimiter + $_.Hash
28
+ }
29
+ $source_files
30
+ }
31
+
32
+ function Get-remote-file-hash($source_path, $delimiter, $session) {
33
+ Invoke-Command -Session $session -ScriptBlock ${function:Get-file-hash} -ArgumentList $source_path, $delimiter
34
+ # TODO:
35
+ # Check if remote PS Scripting errors
36
+ }
37
+
38
+ function Sync-Remote-Machine($machine, $remove_files, $copy_files, $host_path, $guest_path) {
39
+ ForEach ($item in $copy_files) {
40
+ $from = $host_path + $item
41
+ $to = $guest_path + $item
42
+ # Copy VM can also take a VM object
43
+ Copy-VMFile -VM $machine -SourcePath $from -DestinationPath $to -CreateFullPath -FileSource Host -Force
44
+ }
45
+ }
46
+
47
+ function Create-Remote-Folders($empty_source_folders, $guest_path) {
48
+
49
+ ForEach ($item in $empty_source_folders) {
50
+ $new_name = $guest_path + $item
51
+ New-Item "$new_name" -type directory -Force
52
+ }
53
+ }
54
+
55
+ function Create-Guest-Folder($guest_path) {
56
+ try {
57
+ if (Test-Path $guest_path) {
58
+ $junction = Get-Item $guest_path
59
+ $junction.Delete()
60
+ }
61
+ }
62
+ # Catch any [IOException]
63
+ catch {
64
+ Remove-Item "$guest_path" -Force -Recurse
65
+ }
66
+ New-Item "$guest_path" -type directory -Force
67
+ }
68
+
69
+ function Get-Empty-folders-From-Source($host_path) {
70
+ Get-ChildItem $host_path -recurse |
71
+ Where-Object {$_.PSIsContainer -eq $True} |
72
+ Where-Object {$_.GetFiles().Count -eq 0} |
73
+ Select-Object FullName | ForEach-Object -Process {
74
+ $empty_source_folders += ($_.FullName.Replace($host_path, ""))
75
+ }
76
+ }
77
+
78
+ $delimiter = " || "
79
+
80
+ $machine = Get-VM -Id $vm_id
81
+
82
+ # FIXME: PowerShell guys please fix this.
83
+ # The below script checks for all VMIntegrationService which are not enabled
84
+ # and will enable this.
85
+ # When when all the services are enabled this throws an error.
86
+ # Enable VMIntegrationService to true
87
+ try {
88
+ Get-VM -Id $vm_id | Get-VMIntegrationService -Name "Guest Service Interface" | Enable-VMIntegrationService -Passthru
89
+ }
90
+ catch { }
91
+
92
+
93
+ $response = Create-Remote-Session $guest_ip $username $password
94
+ if (!$response["session"] -and $response["error"]) {
95
+ $errortHash = @{
96
+ type = "PowerShellError"
97
+ error = $response["error"]
98
+ }
99
+ Write-Error-Message $errortHash
100
+ return
101
+ }
102
+
103
+ $session = $response["session"]
104
+ # Create the guest folder if not exist
105
+ $result = Invoke-Command -Session $session -ScriptBlock ${function:Create-Guest-Folder} -ArgumentList $guest_path
106
+
107
+
108
+ $source_files = Get-file-hash $host_path $delimiter
109
+ $destination_files = Get-remote-file-hash $guest_path $delimiter $session
110
+
111
+ if (!$destination_files) {
112
+ $destination_files = @()
113
+ }
114
+ if (!$source_files) {
115
+ $source_files = @()
116
+ }
117
+
118
+ # Compare source and destination files
119
+ $remove_files = @()
120
+ $copy_files = @()
121
+
122
+
123
+ Compare-Object -ReferenceObject $source_files -DifferenceObject $destination_files | ForEach-Object {
124
+ if ($_.SideIndicator -eq '=>') {
125
+ $remove_files += $_.InputObject.Split($delimiter)[0]
126
+ } else {
127
+ $copy_files += $_.InputObject.Split($delimiter)[0]
128
+ }
129
+ }
130
+
131
+ # Update the files to remote machine
132
+ Sync-Remote-Machine $machine $remove_files $copy_files $host_path $guest_path
133
+
134
+ # Create any empty folders which missed to sync to remote machine
135
+ $empty_source_folders = @()
136
+ $directories = Get-Empty-folders-From-Source $host_path
137
+
138
+ $result = Invoke-Command -Session $session -ScriptBlock ${function:Create-Remote-Folders} -ArgumentList $empty_source_folders, $guest_path
139
+ # Always remove the connection after Use
140
+ Remove-PSSession -Id $session.Id
141
+
142
+ $resultHash = @{
143
+ message = "OK"
144
+ }
145
+ Write-Output-Message $resultHash
@@ -0,0 +1,25 @@
1
+ #-------------------------------------------------------------------------
2
+ # Copyright (c) Microsoft Open Technologies, Inc.
3
+ # All Rights Reserved. Licensed under the Apache 2.0 License.
4
+ #--------------------------------------------------------------------------
5
+
6
+ # Include the following modules
7
+ $presentDir = Split-Path -parent $PSCommandPath
8
+ . ([System.IO.Path]::Combine($presentDir, "utils\write_messages.ps1"))
9
+
10
+ try {
11
+ $hostname = $(whoami)
12
+ $ip = (Get-WmiObject -class win32_NetworkAdapterConfiguration -Filter 'ipenabled = "true"').ipaddress[0]
13
+ $resultHash = @{
14
+ host_name = "$username"
15
+ host_ip = "$ip"
16
+ }
17
+ Write-Output-Message $resultHash
18
+ }
19
+ catch {
20
+ $errortHash = @{
21
+ type = "PowerShellError"
22
+ error = "$_"
23
+ }
24
+ Write-Error-Message $errortHash
25
+ }
@@ -0,0 +1,36 @@
1
+ #-------------------------------------------------------------------------
2
+ # Copyright (c) Microsoft Open Technologies, Inc.
3
+ # All Rights Reserved. Licensed under the Apache 2.0 License.
4
+ #--------------------------------------------------------------------------
5
+
6
+ param (
7
+ [string]$vm_id = $(throw "-vm_id is required."),
8
+ [string]$command = ""
9
+ )
10
+
11
+ # Include the following modules
12
+ $presentDir = Split-Path -parent $PSCommandPath
13
+ . ([System.IO.Path]::Combine($presentDir, "utils\write_messages.ps1"))
14
+
15
+ try {
16
+ $vm = Get-VM -Id $vm_id -ErrorAction "stop"
17
+ switch ($command) {
18
+ "start" { Start-VM $vm }
19
+ "stop" { Stop-VM $vm }
20
+ "suspend" { Suspend-VM $vm }
21
+ "resume" { Resume-VM $vm }
22
+ }
23
+
24
+ $state = $vm.state
25
+ $status = $vm.status
26
+ $name = $vm.name
27
+ } catch [Microsoft.HyperV.PowerShell.VirtualizationOperationFailedException] {
28
+ $state = "not_created"
29
+ $status = "Not Created"
30
+ }
31
+ $resultHash = @{
32
+ state = "$state"
33
+ status = "$status"
34
+ name = "$name"
35
+ }
36
+ Write-Output-Message $resultHash
@@ -0,0 +1,31 @@
1
+ #-------------------------------------------------------------------------
2
+ # Copyright (c) Microsoft Open Technologies, Inc.
3
+ # All Rights Reserved. Licensed under the Apache 2.0 License.
4
+ #--------------------------------------------------------------------------
5
+
6
+ param (
7
+ [string]$guest_ip = $(throw "-guest_ip is required."),
8
+ [string]$username = $(throw "-guest_username is required."),
9
+ [string]$password = $(throw "-guest_password is required."),
10
+ [string]$command = ""
11
+ )
12
+
13
+ # Include the following modules
14
+ $presentDir = Split-Path -parent $PSCommandPath
15
+ . ([System.IO.Path]::Combine($presentDir, "utils\write_messages.ps1"))
16
+ . ([System.IO.Path]::Combine($presentDir, "utils\create_session.ps1"))
17
+
18
+ try {
19
+ $response = Create-Remote-Session $guest_ip $username $password
20
+ if (!$response["session"] -and $response["error"]) {
21
+ Write-Host $response["error"]
22
+ return
23
+ }
24
+ function Remote-Execute($command) {
25
+ cmd /c $command
26
+ }
27
+ Invoke-Command -Session $response["session"] -ScriptBlock ${function:Remote-Execute} -ArgumentList $command -ErrorAction "stop"
28
+ } catch {
29
+ Write-Host $_
30
+ return
31
+ }
@@ -0,0 +1,95 @@
1
+ #-------------------------------------------------------------------------
2
+ # Copyright (c) Microsoft Open Technologies, Inc.
3
+ # All Rights Reserved. Licensed under the Apache 2.0 License.
4
+ #--------------------------------------------------------------------------
5
+
6
+ param (
7
+ [string]$vm_id = $(throw "-vm_id is required."),
8
+ [string]$host_path = $(throw "-host_path is required."),
9
+ [string]$guest_path = $(throw "-guest_path is required."),
10
+ [string]$guest_ip = $(throw "-guest_ip is required."),
11
+ [string]$username = $(throw "-guest_username is required."),
12
+ [string]$password = $(throw "-guest_password is required.")
13
+ )
14
+
15
+ # Include the following modules
16
+ $presentDir = Split-Path -parent $PSCommandPath
17
+ . ([System.IO.Path]::Combine($presentDir, "utils\write_messages.ps1"))
18
+ . ([System.IO.Path]::Combine($presentDir, "utils\create_session.ps1"))
19
+
20
+ try {
21
+ # Enable Guest Service Interface if they are disabled
22
+ try {
23
+ Get-VM -Id $vm_id | Get-VMIntegrationService -Name "Guest Service Interface" | Enable-VMIntegrationService -Passthru
24
+ }
25
+ catch { }
26
+
27
+ function Upload-FIle-To-VM($host_path, $guest_path, $machine) {
28
+ Write-Host $host_path
29
+ Write-Host $guest_path
30
+ Copy-VMFile -VM $machine -SourcePath $host_path -DestinationPath $guest_path -CreateFullPath -FileSource Host -Force -ErrorAction stop
31
+ }
32
+
33
+ function Prepare-Guest-Folder($guest_ip, $username, $password) {
34
+ $response = Create-Remote-Session $guest_ip $username $password
35
+ if (!$response["session"] -and $response["error"]) {
36
+ $errortHash = @{
37
+ type = "PowerShellError"
38
+ message = $response["error"]
39
+ }
40
+ Write-Error-Message $errorResult
41
+ return
42
+ }
43
+ $session = $response["session"]
44
+ # Create the guest folder if not exist
45
+ $result = Invoke-Command -Session $session -ScriptBlock ${function:Create-Guest-Folder} -ArgumentList $guest_path
46
+ }
47
+
48
+ function Create-Guest-Folder($guest_path) {
49
+ try {
50
+ if (Test-Path $guest_path) {
51
+ # First attempt to remove a Junction drive. The fall back to removing a
52
+ # folder
53
+ $junction = Get-Item $guest_path
54
+ $junction.Delete()
55
+ }
56
+ }
57
+ # Catch any [IOException]
58
+ catch {
59
+ Remove-Item "$guest_path" -Force -Recurse
60
+ }
61
+ New-Item "$guest_path" -type directory -Force
62
+ }
63
+
64
+ $machine = Get-VM -Id $vm_id
65
+ # When Host path is a folder.
66
+ # Find all files within it and copy to the Guest
67
+ if (Test-Path $host_path -pathtype container) {
68
+ # Open a remote PS Session with the guest
69
+ Prepare-Guest-Folder $guest_ip $username $password
70
+ # Copy all files from Host path to Guest Path
71
+ Get-ChildItem $host_path -rec |
72
+ Where-Object {$_.PSIsContainer -eq $false} |
73
+ ForEach-Object -Process {
74
+ $file_name = $_.Fullname.Replace($host_path, "")
75
+ $from = $host_path + $file_name
76
+ $to = $guest_path + $file_name
77
+ # Write-Host $from
78
+ # Write-Host $to
79
+ Upload-FIle-To-VM $from $to $machine
80
+ }
81
+ } elseif (Test-Path $host_path) {
82
+ Upload-FIle-To-VM $host_path $guest_path $machine
83
+ }
84
+ $resultHash = @{
85
+ message = "OK"
86
+ }
87
+ Write-Output-Message $resultHash
88
+ } catch {
89
+ $errortHash = @{
90
+ type = "PowerShellError"
91
+ error ="Failed to copy file $_"
92
+ }
93
+ Write-Error-Message $errortHash
94
+ return
95
+ }
@@ -0,0 +1,34 @@
1
+ #-------------------------------------------------------------------------
2
+ # Copyright (c) Microsoft Open Technologies, Inc.
3
+ # All Rights Reserved. Licensed under the Apache 2.0 License.
4
+ #--------------------------------------------------------------------------
5
+
6
+ function Get-Remote-Session($guest_ip, $username, $password) {
7
+ $secstr = convertto-securestring -AsPlainText -Force -String $password
8
+ $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr
9
+ New-PSSession -ComputerName $guest_ip -Credential $cred -ErrorAction "stop"
10
+ }
11
+
12
+ function Create-Remote-Session($guest_ip, $username, $password) {
13
+ $count = 0
14
+ $session_error = ""
15
+ $session = ""
16
+ do {
17
+ $count++
18
+ try {
19
+ $session = Get-Remote-Session $guest_ip $username $password
20
+ $session_error = ""
21
+ }
22
+ catch {
23
+ Start-Sleep -s 1
24
+ $session_error = $_
25
+ $session = ""
26
+ }
27
+ }
28
+ while (!$session -and $count -lt 20)
29
+
30
+ return @{
31
+ session = $session
32
+ error = $session_error
33
+ }
34
+ }
@@ -0,0 +1,18 @@
1
+ #-------------------------------------------------------------------------
2
+ # Copyright (c) Microsoft Open Technologies, Inc.
3
+ # All Rights Reserved. Licensed under the Apache 2.0 License.
4
+ #--------------------------------------------------------------------------
5
+
6
+ function Write-Error-Message($message) {
7
+ $result = ConvertTo-Json $message
8
+ Write-Host "===Begin-Error==="
9
+ Write-Host $result
10
+ Write-Host "===End-Error==="
11
+ }
12
+
13
+ function Write-Output-Message($message) {
14
+ $result = ConvertTo-Json $message
15
+ Write-Host "===Begin-Output==="
16
+ Write-Host $result
17
+ Write-Host "===End-Output==="
18
+ }
@@ -0,0 +1,10 @@
1
+ #-------------------------------------------------------------------------
2
+ # Copyright (c) Microsoft Open Technologies, Inc.
3
+ # All Rights Reserved. Licensed under the Apache 2.0 License.
4
+ #--------------------------------------------------------------------------
5
+
6
+ module VagrantPlugins
7
+ module VagrantHyperV
8
+ VERSION = "1.0.1"
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ en:
2
+ vagrant_win_hyperv:
3
+ generating_rdp: |-
4
+ Generating a RDP file to establish a remote session. You will soon be prompted to authenticate the
5
+ RDP session and enter the Virtual Machine's password.
6
+ message_rdp_not_ready: |-
7
+ Hyper-V machine isn't running. Can't RDP in!
8
+ errors:
9
+ ssh_not_available: |-
10
+ SSH is available for non windows guest. Vagrant detected guest to be %{guest}
11
+ rdp_not_available: |-
12
+ RDP is available for windows guest. Vagrant detected guest to be %{guest}
13
+ win_rm_not_ready: |-
14
+ WinRM is not enabled in the remot guest. Vagrant-Windows-HyperV uses remote PowerShell scripts
15
+ to communicate to the remote machine. Please check the same and try again.
@@ -0,0 +1,36 @@
1
+ #-------------------------------------------------------------------------
2
+ # Copyright (c) Microsoft Open Technologies, Inc.
3
+ # All Rights Reserved. Licensed under the Apache 2.0 License.
4
+ #--------------------------------------------------------------------------
5
+
6
+ require "vagrant-windows-hyperv/config"
7
+ require_relative "spec_helper"
8
+
9
+ describe VagrantPlugins::HyperV::Config do
10
+ let(:instance) { VagrantPlugins::HyperV::Config.new }
11
+ let(:machine) { Object.new }
12
+ describe "Check host share config" do
13
+ it "Should return the error messages under a key HyperV" do
14
+ instance.host_config do |share|
15
+ share.username = "vagrant"
16
+ end
17
+ error = instance.validate(machine)
18
+ assert(true, error.has_key?("HyperV"))
19
+ end
20
+ it "Should raise errors for missing properties" do
21
+ instance.host_config do |share|
22
+ share.username = "vagrant"
23
+ end
24
+ error = instance.validate(machine)
25
+ assert(true, !error["HyperV"].empty?)
26
+ end
27
+ it "Should have no errors when all properties are passed" do
28
+ instance.host_config do |share|
29
+ share.username = "vagrant"
30
+ share.password = "my_secret_password"
31
+ end
32
+ error = instance.validate(machine)
33
+ assert(true, error["HyperV"].empty?)
34
+ end
35
+ end
36
+ end