kitchen-hyperv 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,205 +1,212 @@
1
- #
2
- # Author:: Steven Murawski <smurawski@chef.io>
3
- # Copyright:: Copyright (c) 2015 Chef Software, Inc.
4
- # License:: Apache License, Version 2.0
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
-
18
- require 'mixlib/shellout'
19
- require 'fileutils'
20
- require 'JSON'
21
-
22
- module Kitchen
23
- module Driver
24
- module PowerShellScripts
25
- def encode_command(script)
26
- encoded_script = script.encode('UTF-16LE', 'UTF-8')
27
- Base64.strict_encode64(encoded_script)
28
- end
29
-
30
- def is_64bit?
31
- os_arch = ENV['PROCESSOR_ARCHITEW6432'] || ENV['PROCESSOR_ARCHITECTURE']
32
- ruby_arch = ['foo'].pack('p').size == 4 ? 32 : 64
33
- os_arch == 'AMD64' && ruby_arch == 64
34
- end
35
-
36
- def is_32bit?
37
- os_arch = ENV['PROCESSOR_ARCHITEW6432'] || ENV['PROCESSOR_ARCHITECTURE']
38
- ruby_arch = ['foo'].pack('p').size == 4 ? 32 : 64
39
- os_arch != 'AMD64' && ruby_arch == 32
40
- end
41
-
42
- def powershell_64_bit
43
- if is_64bit? || is_32bit?
44
- 'c:\windows\system32\windowspowershell\v1.0\powershell.exe'
45
- else
46
- 'c:\windows\sysnative\windowspowershell\v1.0\powershell.exe'
47
- end
48
- end
49
-
50
- def wrap_command(script)
51
- base_script_path = File.join(File.dirname(__FILE__), '/../../../support/hyperv.ps1')
52
- debug("Loading functions from #{base_script_path}")
53
- new_script = [ ". #{base_script_path}", "#{script}" ].join(";\n")
54
- debug("Wrapped script: #{new_script}")
55
- "#{powershell_64_bit} -noprofile -executionpolicy bypass" \
56
- " -encodedcommand #{encode_command new_script} -outputformat Text"
57
- end
58
-
59
- # Convenience method to run a powershell command locally.
60
- #
61
- # @param cmd [String] command to run locally
62
- # @param options [Hash] options hash
63
- # @see Kitchen::ShellOut.run_command
64
- # @api private
65
- def run_ps(cmd, options = {})
66
- cmd = "echo #{cmd}" if config[:dry_run]
67
- debug('Preparing to run: ')
68
- debug(" #{cmd}")
69
- wrapped_command = wrap_command cmd
70
- execute_command wrapped_command, options
71
- end
72
-
73
- def execute_command(cmd, options = {})
74
- debug("#Local Command BEGIN (#{cmd})")
75
- sh = Mixlib::ShellOut.new(cmd, options)
76
- sh.run_command
77
- debug("Local Command END #{Util.duration(sh.execution_time)}")
78
- raise "Failed: #{sh.stderr}" if sh.error?
79
- stdout = sanitize_stdout(sh.stdout)
80
- JSON.parse(stdout) if stdout.length > 2
81
- end
82
-
83
- def sanitize_stdout(stdout)
84
- stdout.split("\n").select { |s| !s.start_with?("PS") }.join("\n")
85
- end
86
-
87
- def new_differencing_disk_ps
88
- <<-DIFF
89
-
90
- New-DifferencingDisk -Path "#{differencing_disk_path}" -ParentPath "#{parent_vhd_path}"
91
- DIFF
92
- end
93
-
94
- def ensure_vm_running_ps
95
- <<-RUNNING
96
-
97
- Assert-VmRunning -ID "#{@state[:id]}" | ConvertTo-Json
98
- RUNNING
99
- end
100
-
101
- def new_vm_ps
102
- <<-NEWVM
103
-
104
- $NewVMParams = @{
105
- Generation = #{config[:vm_generation]}
106
- MemoryStartupBytes = #{config[:memory_startup_bytes]}
107
- Name = "#{instance.name}"
108
- Path = "#{kitchen_vm_path}"
109
- VHDPath = "#{differencing_disk_path}"
110
- SwitchName = "#{config[:vm_switch]}"
111
- ProcessorCount = #{config[:processor_count]}
112
- UseDynamicMemory = "#{config[:dynamic_memory]}"
113
- DynamicMemoryMinBytes = #{config[:dynamic_memory_min_bytes]}
114
- DynamicMemoryMaxBytes = #{config[:dynamic_memory_max_bytes]}
115
- boot_iso_path = "#{boot_iso_path}"
116
- }
117
- New-KitchenVM @NewVMParams | ConvertTo-Json
118
- NEWVM
119
- end
120
-
121
- def vm_details_ps
122
- <<-DETAILS
123
-
124
- Get-VmDetail -id "#{@state[:id]}" | ConvertTo-Json
125
- DETAILS
126
- end
127
-
128
- def delete_vm_ps
129
- <<-REMOVE
130
-
131
- $null = Get-VM -ID "#{@state[:id]}" |
132
- Stop-VM -Force -TurnOff -PassThru |
133
- Remove-VM -Force
134
- REMOVE
135
- end
136
-
137
- def set_vm_ipaddress_ps
138
- <<-VMIP
139
-
140
- (Get-VM -id "#{@state[:id]}").NetworkAdapters |
141
- Set-VMNetworkConfiguration -ipaddress "#{config[:ip_address]}" `
142
- -subnet "#{config[:subnet]}" `
143
- -gateway "#{config[:gateway]}" `
144
- -dnsservers #{ruby_array_to_ps_array(config[:dns_servers])} |
145
- ConvertTo-Json
146
- VMIP
147
- end
148
-
149
- def vm_default_switch_ps
150
- <<-VMSWITCH
151
- Get-DefaultVMSwitch #{config[:vm_switch]} | ConvertTo-Json
152
- VMSWITCH
153
- end
154
-
155
- def mount_vm_iso
156
- <<-MOUNTISO
157
- mount-vmiso -id "#{@state[:id]}" -Path #{config[:iso_path]}
158
- MOUNTISO
159
- end
160
-
161
- def copy_vm_file_ps(source, dest)
162
- <<-FILECOPY
163
- Function CopyFile ($VM, [string]$SourcePath, [string]$DestPath) {
164
- $p = @{ CreateFullPath = $true ; FileSource = 'Host'; Force = $true }
165
- $VM |
166
- Copy-VMFile -SourcePath $SourcePath -DestinationPath $DestPath @p
167
- }
168
-
169
- $sourceLocation = '#{source}'
170
- $destinationLocation = '#{dest}'
171
- $vmId = '#{@state[:id]}'
172
- If (Test-Path $sourceLocation) {
173
- $vm = Get-VM -ID $vmId
174
- $service = 'Guest Service Interface'
175
-
176
- If ((Get-VMIntegrationService -Name $service -VM $vm).Enabled -ne $true) {
177
- Enable-VMIntegrationService -Name $service -VM $vm
178
- Start-Sleep -Seconds 3
179
- }
180
-
181
- If ((Get-Item $sourceLocation) -is [System.IO.DirectoryInfo]) {
182
- ForEach ($item in (Get-ChildItem -Path $sourceLocation -File)) {
183
- $destFullPath = (Join-Path $destinationLocation $item.Name)
184
- CopyFile $vm $item.FullName $destFullPath
185
- }
186
- }
187
- Else {
188
- CopyFile $vm $sourceLocation $destinationLocation
189
- }
190
- }
191
- else {
192
- Write-Error "Source file path does not exist: $sourceLocation"
193
- }
194
- FILECOPY
195
- end
196
-
197
- private
198
-
199
- def ruby_array_to_ps_array(list)
200
- return "@()" if list.nil? || list.empty?
201
- list.to_s.tr('[]','()').prepend('@')
202
- end
203
- end
204
- end
205
- end
1
+ #
2
+ # Author:: Steven Murawski <smurawski@chef.io>
3
+ # Copyright:: Copyright (c) 2015 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require 'mixlib/shellout'
19
+ require 'fileutils'
20
+ require 'JSON'
21
+
22
+ module Kitchen
23
+ module Driver
24
+ module PowerShellScripts
25
+ def encode_command(script)
26
+ encoded_script = script.encode('UTF-16LE', 'UTF-8')
27
+ Base64.strict_encode64(encoded_script)
28
+ end
29
+
30
+ def is_64bit?
31
+ os_arch = ENV['PROCESSOR_ARCHITEW6432'] || ENV['PROCESSOR_ARCHITECTURE']
32
+ ruby_arch = ['foo'].pack('p').size == 4 ? 32 : 64
33
+ os_arch == 'AMD64' && ruby_arch == 64
34
+ end
35
+
36
+ def is_32bit?
37
+ os_arch = ENV['PROCESSOR_ARCHITEW6432'] || ENV['PROCESSOR_ARCHITECTURE']
38
+ ruby_arch = ['foo'].pack('p').size == 4 ? 32 : 64
39
+ os_arch != 'AMD64' && ruby_arch == 32
40
+ end
41
+
42
+ def powershell_64_bit
43
+ if is_64bit? || is_32bit?
44
+ 'c:\windows\system32\windowspowershell\v1.0\powershell.exe'
45
+ else
46
+ 'c:\windows\sysnative\windowspowershell\v1.0\powershell.exe'
47
+ end
48
+ end
49
+
50
+ def wrap_command(script)
51
+ base_script_path = File.join(File.dirname(__FILE__), '/../../../support/hyperv.ps1')
52
+ debug("Loading functions from #{base_script_path}")
53
+ new_script = [ ". #{base_script_path}", "#{script}" ].join(";\n")
54
+ debug("Wrapped script: #{new_script}")
55
+ "#{powershell_64_bit} -noprofile -executionpolicy bypass" \
56
+ " -encodedcommand #{encode_command new_script} -outputformat Text"
57
+ end
58
+
59
+ # Convenience method to run a powershell command locally.
60
+ #
61
+ # @param cmd [String] command to run locally
62
+ # @param options [Hash] options hash
63
+ # @see Kitchen::ShellOut.run_command
64
+ # @api private
65
+ def run_ps(cmd, options = {})
66
+ cmd = "echo #{cmd}" if config[:dry_run]
67
+ debug('Preparing to run: ')
68
+ debug(" #{cmd}")
69
+ wrapped_command = wrap_command cmd
70
+ execute_command wrapped_command, options
71
+ end
72
+
73
+ def execute_command(cmd, options = {})
74
+ debug("#Local Command BEGIN (#{cmd})")
75
+ sh = Mixlib::ShellOut.new(cmd, options)
76
+ sh.run_command
77
+ debug("Local Command END #{Util.duration(sh.execution_time)}")
78
+ raise "Failed: #{sh.stderr}" if sh.error?
79
+ stdout = sanitize_stdout(sh.stdout)
80
+ JSON.parse(stdout) if stdout.length > 2
81
+ end
82
+
83
+ def sanitize_stdout(stdout)
84
+ stdout.split("\n").select { |s| !s.start_with?("PS") }.join("\n")
85
+ end
86
+
87
+ def new_differencing_disk_ps
88
+ <<-DIFF
89
+
90
+ New-DifferencingDisk -Path "#{differencing_disk_path}" -ParentPath "#{parent_vhd_path}"
91
+ DIFF
92
+ end
93
+
94
+ def ensure_vm_running_ps
95
+ <<-RUNNING
96
+
97
+ Assert-VmRunning -ID "#{@state[:id]}" | ConvertTo-Json
98
+ RUNNING
99
+ end
100
+
101
+ def new_vm_ps
102
+ <<-NEWVM
103
+
104
+ $NewVMParams = @{
105
+ Generation = #{config[:vm_generation]}
106
+ MemoryStartupBytes = #{config[:memory_startup_bytes]}
107
+ Name = "#{instance.name}"
108
+ Path = "#{kitchen_vm_path}"
109
+ VHDPath = "#{differencing_disk_path}"
110
+ SwitchName = "#{config[:vm_switch]}"
111
+ ProcessorCount = #{config[:processor_count]}
112
+ UseDynamicMemory = "#{config[:dynamic_memory]}"
113
+ DynamicMemoryMinBytes = #{config[:dynamic_memory_min_bytes]}
114
+ DynamicMemoryMaxBytes = #{config[:dynamic_memory_max_bytes]}
115
+ boot_iso_path = "#{boot_iso_path}"
116
+ EnableGuestServices = "#{config[:enable_guest_services]}"
117
+ }
118
+ New-KitchenVM @NewVMParams | ConvertTo-Json
119
+ NEWVM
120
+ end
121
+
122
+ def vm_details_ps
123
+ <<-DETAILS
124
+
125
+ Get-VmDetail -id "#{@state[:id]}" | ConvertTo-Json
126
+ DETAILS
127
+ end
128
+
129
+ def delete_vm_ps
130
+ <<-REMOVE
131
+
132
+ $null = Get-VM -ID "#{@state[:id]}" |
133
+ Stop-VM -Force -TurnOff -PassThru |
134
+ Remove-VM -Force
135
+ REMOVE
136
+ end
137
+
138
+ def set_vm_ipaddress_ps
139
+ <<-VMIP
140
+
141
+ (Get-VM -id "#{@state[:id]}").NetworkAdapters |
142
+ Set-VMNetworkConfiguration -ipaddress "#{config[:ip_address]}" `
143
+ -subnet "#{config[:subnet]}" `
144
+ -gateway "#{config[:gateway]}" `
145
+ -dnsservers #{ruby_array_to_ps_array(config[:dns_servers])} |
146
+ ConvertTo-Json
147
+ VMIP
148
+ end
149
+
150
+ def vm_default_switch_ps
151
+ <<-VMSWITCH
152
+ Get-DefaultVMSwitch #{config[:vm_switch]} | ConvertTo-Json
153
+ VMSWITCH
154
+ end
155
+
156
+ def mount_vm_iso
157
+ <<-MOUNTISO
158
+ mount-vmiso -id "#{@state[:id]}" -Path #{config[:iso_path]}
159
+ MOUNTISO
160
+ end
161
+
162
+ def set_vm_note
163
+ <<-VMNOTE
164
+ Set-VM -Name (Get-VM | Where-Object{ $_.ID -eq "#{@state[:id]}"}).Name -Note "#{config[:vm_note]}"
165
+ VMNOTE
166
+ end
167
+
168
+ def copy_vm_file_ps(source, dest)
169
+ <<-FILECOPY
170
+ Function CopyFile ($VM, [string]$SourcePath, [string]$DestPath) {
171
+ $p = @{ CreateFullPath = $true ; FileSource = 'Host'; Force = $true }
172
+ $VM |
173
+ Copy-VMFile -SourcePath $SourcePath -DestinationPath $DestPath @p
174
+ }
175
+
176
+ $sourceLocation = '#{source}'
177
+ $destinationLocation = '#{dest}'
178
+ $vmId = '#{@state[:id]}'
179
+ If (Test-Path $sourceLocation) {
180
+ $vm = Get-VM -ID $vmId
181
+ $service = 'Guest Service Interface'
182
+
183
+ If ((Get-VMIntegrationService -Name $service -VM $vm).Enabled -ne $true) {
184
+ Enable-VMIntegrationService -Name $service -VM $vm
185
+ Start-Sleep -Seconds 3
186
+ }
187
+
188
+ If ((Get-Item $sourceLocation) -is [System.IO.DirectoryInfo]) {
189
+ ForEach ($item in (Get-ChildItem -Path $sourceLocation -File)) {
190
+ $destFullPath = (Join-Path $destinationLocation $item.Name)
191
+ CopyFile $vm $item.FullName $destFullPath
192
+ }
193
+ }
194
+ Else {
195
+ CopyFile $vm $sourceLocation $destinationLocation
196
+ }
197
+ }
198
+ else {
199
+ Write-Error "Source file path does not exist: $sourceLocation"
200
+ }
201
+ FILECOPY
202
+ end
203
+
204
+ private
205
+
206
+ def ruby_array_to_ps_array(list)
207
+ return "@()" if list.nil? || list.empty?
208
+ list.to_s.tr('[]','()').prepend('@')
209
+ end
210
+ end
211
+ end
212
+ end
@@ -1,70 +1,70 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Fletcher (<fnichol@nichol.ca>)
4
- #
5
- # Copyright (C) 2015, Fletcher Nichol
6
- #
7
- # Licensed under the Apache License, Version 2.0 (the "License");
8
- # you may not use this file except in compliance with the License.
9
- # You may obtain a copy of the License at
10
- #
11
- # http://www.apache.org/licenses/LICENSE-2.0
12
- #
13
- # Unless required by applicable law or agreed to in writing, software
14
- # distributed under the License is distributed on an "AS IS" BASIS,
15
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- # See the License for the specific language governing permissions and
17
- # limitations under the License.
18
-
19
- require_relative "../../spec_helper"
20
-
21
- require "logger"
22
- require "stringio"
23
- require "kitchen"
24
- require 'kitchen/driver/hyperv_version'
25
- require "kitchen/driver/hyperv"
26
- require "kitchen/provisioner/dummy"
27
- require "kitchen/transport/dummy"
28
- require "kitchen/verifier/dummy"
29
-
30
- describe Kitchen::Driver::Hyperv do
31
-
32
- let(:logged_output) { StringIO.new }
33
- let(:logger) { Logger.new(logged_output) }
34
- let(:config) { { :kitchen_root => "c:/test_root" } }
35
- let(:platform) { Kitchen::Platform.new(:name => "fooos-99") }
36
- let(:suite) { Kitchen::Suite.new(:name => "suitey") }
37
- let(:verifier) { Kitchen::Verifier::Dummy.new }
38
- let(:provisioner) { Kitchen::Provisioner::Dummy.new }
39
- let(:transport) { Kitchen::Transport::Dummy.new }
40
- let(:state_file) { stub("state_file") }
41
- let(:state) { Hash.new }
42
- let(:env) { Hash.new }
43
-
44
- let(:driver_object) { Kitchen::Driver::Hyperv.new(config) }
45
-
46
- let(:driver) do
47
- d = driver_object
48
- instance
49
- d
50
- end
51
-
52
- let(:instance) do
53
- Kitchen::Instance.new(
54
- :verifier => verifier,
55
- :driver => driver_object,
56
- :logger => logger,
57
- :suite => suite,
58
- :platform => platform,
59
- :provisioner => provisioner,
60
- :transport => transport,
61
- :state_file => state_file
62
- )
63
- end
64
-
65
- #before { stub_const("ENV", env) }
66
-
67
- it 'driver api_version is 2' do
68
- driver.diagnose_plugin[:api_version].must_equal(2)
69
- end
70
- end
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2015, Fletcher Nichol
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ require_relative "../../spec_helper"
20
+
21
+ require "logger"
22
+ require "stringio"
23
+ require "kitchen"
24
+ require 'kitchen/driver/hyperv_version'
25
+ require "kitchen/driver/hyperv"
26
+ require "kitchen/provisioner/dummy"
27
+ require "kitchen/transport/dummy"
28
+ require "kitchen/verifier/dummy"
29
+
30
+ describe Kitchen::Driver::Hyperv do
31
+
32
+ let(:logged_output) { StringIO.new }
33
+ let(:logger) { Logger.new(logged_output) }
34
+ let(:config) { { :kitchen_root => "c:/test_root" } }
35
+ let(:platform) { Kitchen::Platform.new(:name => "fooos-99") }
36
+ let(:suite) { Kitchen::Suite.new(:name => "suitey") }
37
+ let(:verifier) { Kitchen::Verifier::Dummy.new }
38
+ let(:provisioner) { Kitchen::Provisioner::Dummy.new }
39
+ let(:transport) { Kitchen::Transport::Dummy.new }
40
+ let(:state_file) { stub("state_file") }
41
+ let(:state) { Hash.new }
42
+ let(:env) { Hash.new }
43
+
44
+ let(:driver_object) { Kitchen::Driver::Hyperv.new(config) }
45
+
46
+ let(:driver) do
47
+ d = driver_object
48
+ instance
49
+ d
50
+ end
51
+
52
+ let(:instance) do
53
+ Kitchen::Instance.new(
54
+ :verifier => verifier,
55
+ :driver => driver_object,
56
+ :logger => logger,
57
+ :suite => suite,
58
+ :platform => platform,
59
+ :provisioner => provisioner,
60
+ :transport => transport,
61
+ :state_file => state_file
62
+ )
63
+ end
64
+
65
+ #before { stub_const("ENV", env) }
66
+
67
+ it 'driver api_version is 2' do
68
+ driver.diagnose_plugin[:api_version].must_equal(2)
69
+ end
70
+ end