kitchen-hyperv 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,22 +1,22 @@
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
- module Kitchen
19
- module Driver
20
- HYPERV_VERSION = '0.4.1'.freeze
21
- end
22
- 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
+ module Kitchen
19
+ module Driver
20
+ HYPERV_VERSION = '0.5.0'.freeze
21
+ end
22
+ end
@@ -1,235 +1,236 @@
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 new_additional_disk_ps(disk_path, disk_size)
95
- <<-ADDDISK
96
-
97
- New-VHD -Path "#{disk_path}" -SizeBytes #{disk_size}GB | Out-Null
98
- ADDDISK
99
- end
100
-
101
- def ensure_vm_running_ps
102
- <<-RUNNING
103
-
104
- Assert-VmRunning -ID "#{@state[:id]}" | ConvertTo-Json
105
- RUNNING
106
- end
107
-
108
- def new_vm_ps
109
- <<-NEWVM
110
-
111
- $NewVMParams = @{
112
- Generation = #{config[:vm_generation]}
113
- DisableSecureBoot = "#{config[:disable_secureboot]}"
114
- MemoryStartupBytes = #{config[:memory_startup_bytes]}
115
- Name = "#{instance.name}"
116
- Path = "#{kitchen_vm_path}"
117
- VHDPath = "#{differencing_disk_path}"
118
- SwitchName = "#{config[:vm_switch]}"
119
- VlanId = #{config[:vm_vlan_id] || '$null'}
120
- ProcessorCount = #{config[:processor_count]}
121
- UseDynamicMemory = "#{config[:dynamic_memory]}"
122
- DynamicMemoryMinBytes = #{config[:dynamic_memory_min_bytes]}
123
- DynamicMemoryMaxBytes = #{config[:dynamic_memory_max_bytes]}
124
- boot_iso_path = "#{boot_iso_path}"
125
- EnableGuestServices = "#{config[:enable_guest_services]}"
126
- #{additional_disks}
127
- }
128
- New-KitchenVM @NewVMParams | ConvertTo-Json
129
- NEWVM
130
- end
131
-
132
- def additional_disks
133
- return if config[:additional_disks].nil?
134
- <<-EOH
135
- AdditionalDisks = @("#{@additional_disk_objects.join('","')}")
136
- EOH
137
- end
138
-
139
- def vm_details_ps
140
- <<-DETAILS
141
-
142
- Get-VmDetail -id "#{@state[:id]}" | ConvertTo-Json
143
- DETAILS
144
- end
145
-
146
- def delete_vm_ps
147
- <<-REMOVE
148
-
149
- $null = Get-VM -ID "#{@state[:id]}" |
150
- Stop-VM -Force -TurnOff -PassThru |
151
- Remove-VM -Force
152
- REMOVE
153
- end
154
-
155
- def set_vm_ipaddress_ps
156
- <<-VMIP
157
-
158
- (Get-VM -id "#{@state[:id]}").NetworkAdapters |
159
- Set-VMNetworkConfiguration -ipaddress "#{config[:ip_address]}" `
160
- -subnet "#{config[:subnet]}" `
161
- -gateway "#{config[:gateway]}" `
162
- -dnsservers #{ruby_array_to_ps_array(config[:dns_servers])} |
163
- ConvertTo-Json
164
- VMIP
165
- end
166
-
167
- def vm_default_switch_ps
168
- <<-VMSWITCH
169
- Get-DefaultVMSwitch #{config[:vm_switch]} | ConvertTo-Json
170
- VMSWITCH
171
- end
172
-
173
- def mount_vm_iso
174
- <<-MOUNTISO
175
- mount-vmiso -id "#{@state[:id]}" -Path #{config[:iso_path]}
176
- MOUNTISO
177
- end
178
-
179
- def resize_vhd
180
- <<-VMNOTE
181
- Resize-VHD -Path "#{parent_vhd_path}" -Size #{config[:resize_vhd]}
182
- VMNOTE
183
- end
184
-
185
- def set_vm_note
186
- <<-VMNOTE
187
- Set-VM -Name (Get-VM | Where-Object{ $_.ID -eq "#{@state[:id]}"}).Name -Note "#{config[:vm_note]}"
188
- VMNOTE
189
- end
190
-
191
- def copy_vm_file_ps(source, dest)
192
- <<-FILECOPY
193
- Function CopyFile ($VM, [string]$SourcePath, [string]$DestPath) {
194
- $p = @{ CreateFullPath = $true ; FileSource = 'Host'; Force = $true }
195
- $VM |
196
- Copy-VMFile -SourcePath $SourcePath -DestinationPath $DestPath @p
197
- }
198
-
199
- $sourceLocation = '#{source}'
200
- $destinationLocation = '#{dest}'
201
- $vmId = '#{@state[:id]}'
202
- If (Test-Path $sourceLocation) {
203
- $vm = Get-VM -ID $vmId
204
- $service = 'Guest Service Interface'
205
-
206
- If ((Get-VMIntegrationService -Name $service -VM $vm).Enabled -ne $true) {
207
- Enable-VMIntegrationService -Name $service -VM $vm
208
- Start-Sleep -Seconds 3
209
- }
210
-
211
- If ((Get-Item $sourceLocation) -is [System.IO.DirectoryInfo]) {
212
- ForEach ($item in (Get-ChildItem -Path $sourceLocation -File)) {
213
- $destFullPath = (Join-Path $destinationLocation $item.Name)
214
- CopyFile $vm $item.FullName $destFullPath
215
- }
216
- }
217
- Else {
218
- CopyFile $vm $sourceLocation $destinationLocation
219
- }
220
- }
221
- else {
222
- Write-Error "Source file path does not exist: $sourceLocation"
223
- }
224
- FILECOPY
225
- end
226
-
227
- private
228
-
229
- def ruby_array_to_ps_array(list)
230
- return "@()" if list.nil? || list.empty?
231
- list.to_s.tr('[]','()').prepend('@')
232
- end
233
- end
234
- end
235
- 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 new_additional_disk_ps(disk_path, disk_size)
95
+ <<-ADDDISK
96
+
97
+ New-VHD -Path "#{disk_path}" -SizeBytes #{disk_size}GB | Out-Null
98
+ ADDDISK
99
+ end
100
+
101
+ def ensure_vm_running_ps
102
+ <<-RUNNING
103
+
104
+ Assert-VmRunning -ID "#{@state[:id]}" | ConvertTo-Json
105
+ RUNNING
106
+ end
107
+
108
+ def new_vm_ps
109
+ <<-NEWVM
110
+
111
+ $NewVMParams = @{
112
+ Generation = #{config[:vm_generation]}
113
+ DisableSecureBoot = "#{config[:disable_secureboot]}"
114
+ MemoryStartupBytes = #{config[:memory_startup_bytes]}
115
+ StaticMacAddress = "#{config[:static_mac_address]}"
116
+ Name = "#{instance.name}"
117
+ Path = "#{kitchen_vm_path}"
118
+ VHDPath = "#{differencing_disk_path}"
119
+ SwitchName = "#{config[:vm_switch]}"
120
+ VlanId = #{config[:vm_vlan_id] || '$null'}
121
+ ProcessorCount = #{config[:processor_count]}
122
+ UseDynamicMemory = "#{config[:dynamic_memory]}"
123
+ DynamicMemoryMinBytes = #{config[:dynamic_memory_min_bytes]}
124
+ DynamicMemoryMaxBytes = #{config[:dynamic_memory_max_bytes]}
125
+ boot_iso_path = "#{boot_iso_path}"
126
+ EnableGuestServices = "#{config[:enable_guest_services]}"
127
+ #{additional_disks}
128
+ }
129
+ New-KitchenVM @NewVMParams | ConvertTo-Json
130
+ NEWVM
131
+ end
132
+
133
+ def additional_disks
134
+ return if config[:additional_disks].nil?
135
+ <<-EOH
136
+ AdditionalDisks = @("#{@additional_disk_objects.join('","')}")
137
+ EOH
138
+ end
139
+
140
+ def vm_details_ps
141
+ <<-DETAILS
142
+
143
+ Get-VmDetail -id "#{@state[:id]}" | ConvertTo-Json
144
+ DETAILS
145
+ end
146
+
147
+ def delete_vm_ps
148
+ <<-REMOVE
149
+
150
+ $null = Get-VM -ID "#{@state[:id]}" |
151
+ Stop-VM -Force -TurnOff -PassThru |
152
+ Remove-VM -Force
153
+ REMOVE
154
+ end
155
+
156
+ def set_vm_ipaddress_ps
157
+ <<-VMIP
158
+
159
+ (Get-VM -id "#{@state[:id]}").NetworkAdapters |
160
+ Set-VMNetworkConfiguration -ipaddress "#{config[:ip_address]}" `
161
+ -subnet "#{config[:subnet]}" `
162
+ -gateway "#{config[:gateway]}" `
163
+ -dnsservers #{ruby_array_to_ps_array(config[:dns_servers])} |
164
+ ConvertTo-Json
165
+ VMIP
166
+ end
167
+
168
+ def vm_default_switch_ps
169
+ <<-VMSWITCH
170
+ Get-DefaultVMSwitch #{config[:vm_switch]} | ConvertTo-Json
171
+ VMSWITCH
172
+ end
173
+
174
+ def mount_vm_iso
175
+ <<-MOUNTISO
176
+ mount-vmiso -id "#{@state[:id]}" -Path #{config[:iso_path]}
177
+ MOUNTISO
178
+ end
179
+
180
+ def resize_vhd
181
+ <<-VMNOTE
182
+ Resize-VHD -Path "#{parent_vhd_path}" -Size #{config[:resize_vhd]}
183
+ VMNOTE
184
+ end
185
+
186
+ def set_vm_note
187
+ <<-VMNOTE
188
+ Set-VM -Name (Get-VM | Where-Object{ $_.ID -eq "#{@state[:id]}"}).Name -Note "#{config[:vm_note]}"
189
+ VMNOTE
190
+ end
191
+
192
+ def copy_vm_file_ps(source, dest)
193
+ <<-FILECOPY
194
+ Function CopyFile ($VM, [string]$SourcePath, [string]$DestPath) {
195
+ $p = @{ CreateFullPath = $true ; FileSource = 'Host'; Force = $true }
196
+ $VM |
197
+ Copy-VMFile -SourcePath $SourcePath -DestinationPath $DestPath @p
198
+ }
199
+
200
+ $sourceLocation = '#{source}'
201
+ $destinationLocation = '#{dest}'
202
+ $vmId = '#{@state[:id]}'
203
+ If (Test-Path $sourceLocation) {
204
+ $vm = Get-VM -ID $vmId
205
+ $service = 'Guest Service Interface'
206
+
207
+ If ((Get-VMIntegrationService -Name $service -VM $vm).Enabled -ne $true) {
208
+ Enable-VMIntegrationService -Name $service -VM $vm
209
+ Start-Sleep -Seconds 3
210
+ }
211
+
212
+ If ((Get-Item $sourceLocation) -is [System.IO.DirectoryInfo]) {
213
+ ForEach ($item in (Get-ChildItem -Path $sourceLocation -File)) {
214
+ $destFullPath = (Join-Path $destinationLocation $item.Name)
215
+ CopyFile $vm $item.FullName $destFullPath
216
+ }
217
+ }
218
+ Else {
219
+ CopyFile $vm $sourceLocation $destinationLocation
220
+ }
221
+ }
222
+ else {
223
+ Write-Error "Source file path does not exist: $sourceLocation"
224
+ }
225
+ FILECOPY
226
+ end
227
+
228
+ private
229
+
230
+ def ruby_array_to_ps_array(list)
231
+ return "@()" if list.nil? || list.empty?
232
+ list.to_s.tr('[]','()').prepend('@')
233
+ end
234
+ end
235
+ end
236
+ end