kitchen-hyperv 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7588944a18673c39d89916777a86bfd20fefada1
4
+ data.tar.gz: f11736929cca5a1c06ce00e8b27e9f8821991992
5
+ SHA512:
6
+ metadata.gz: 51c6e027033709b450e949468550bf3bad75a2ab43e6c32a972d21d40f9cd75329e0624b62b6bdd9137fa6827e4b0838c5df1fcc9762b6e00cf0dc9eb9800ab3
7
+ data.tar.gz: 113b8020c4d1f4e25941d7699cb494851f45eac56e09aa38ac0179a419d85f7f9569865ab3648aabbcafca62aa8ac22d2bb43e247f1cfcaf1a847dede9e9d70d
data/.cane ADDED
@@ -0,0 +1,2 @@
1
+ --no-doc
2
+ --style-measure 100
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rubocop.yml ADDED
@@ -0,0 +1,5 @@
1
+ Metrics/LineLength:
2
+ Max: 100
3
+
4
+ Style/Documentation:
5
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in kitchen-hyperv.gemspec
4
+ gemspec
5
+
6
+ gem 'win32-process'
7
+ gem 'win32-api'
8
+ gem 'windows-pr'
9
+ gem 'windows-api'
10
+ gem 'ffi'
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Steven Murawski
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Kitchen::Hyperv
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'kitchen-hyperv'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install kitchen-hyperv
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/kitchen-hyperv/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,52 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require "bundler/gem_tasks"
4
+
5
+ require "rake/testtask"
6
+ Rake::TestTask.new(:unit) do |t|
7
+ t.libs.push "lib"
8
+ t.test_files = FileList["spec/**/*_spec.rb"]
9
+ t.verbose = true
10
+ end
11
+
12
+ desc "Run all test suites"
13
+ task :test => [:unit]
14
+
15
+ desc "Display LOC stats"
16
+ task :stats do
17
+ puts "\n## Production Code Stats"
18
+ sh "countloc -r lib"
19
+ puts "\n## Test Code Stats"
20
+ sh "countloc -r spec"
21
+ end
22
+
23
+ require "finstyle"
24
+ require "rubocop/rake_task"
25
+ RuboCop::RakeTask.new(:style) do |task|
26
+ task.options << "--display-cop-names"
27
+ task.options << "--lint"
28
+ task.options << '--config' << '.rubocop.yml'
29
+ task.patterns = ['lib/**/*.rb']
30
+ end
31
+
32
+ require "cane/rake_task"
33
+ desc "Run cane to check quality metrics"
34
+ Cane::RakeTask.new do |cane|
35
+ cane.canefile = "./.cane"
36
+ end
37
+
38
+ desc "Run all quality tasks"
39
+ task :quality => [:cane, :style, :stats]
40
+
41
+ require "yard"
42
+ YARD::Rake::YardocTask.new
43
+
44
+ desc "Generate gem dependency graph"
45
+ task :viz do
46
+ Bundler.with_clean_env do
47
+ sh "bundle viz --without test development guard " \
48
+ "--requirements --version"
49
+ end
50
+ end
51
+
52
+ task :default => [:test, :quality]
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require 'kitchen/driver/hyperv_version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "kitchen-hyperv"
9
+ spec.version = Kitchen::Driver::HYPERV_VERSION
10
+ spec.authors = ["Steven Murawski"]
11
+ spec.email = ["steven.murawski@gmail.com"]
12
+ spec.summary = 'Hyper-V Driver for Test-Kitchen'
13
+ spec.description = 'Hyper-V Driver for Test-Kitchen'
14
+ spec.homepage = ""
15
+ spec.license = "Apache 2"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.7"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "pry", "~> 0.10"
25
+
26
+ spec.add_dependency "test-kitchen", "~> 1.4"
27
+ end
@@ -0,0 +1,139 @@
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
+
19
+ require 'kitchen'
20
+ require 'kitchen/driver'
21
+ require 'kitchen/driver/hyperv_version'
22
+ require 'kitchen/driver/powershell'
23
+ require 'mixlib/shellout'
24
+ require 'fileutils'
25
+ require 'JSON'
26
+
27
+ module Kitchen
28
+
29
+ module Driver
30
+
31
+ # Driver for Hyper-V
32
+ class Hyperv < Kitchen::Driver::Base
33
+
34
+ kitchen_driver_api_version 2
35
+ plugin_version Kitchen::Driver::HYPERV_VERSION
36
+
37
+ default_config :parent_vhd_folder
38
+ default_config :parent_vhd_name
39
+ default_config :memory_startup_bytes, 536_870_912
40
+ default_config :processor_count, 2
41
+ default_config :password
42
+ # because test-kitchen defaults to the wrong value
43
+ default_config :username, 'Administrator'
44
+ default_config :ip_address
45
+ default_config :vm_switch
46
+
47
+ include Kitchen::Driver::PowerShellScripts
48
+
49
+ def create(state)
50
+ @state = state
51
+ validate_vm_settings
52
+ create_new_differencing_disk
53
+ create_virtual_machine
54
+ update_state
55
+ instance.transport.connection(@state).wait_until_ready
56
+ info("Hyper-V instance #{instance.to_str} created.")
57
+ end
58
+
59
+ def destroy(state)
60
+ @state = state
61
+ return unless vm_exists
62
+ instance.transport.connection(state).close
63
+ remove_virtual_machine
64
+ remove_differencing_disk
65
+ info("The Hyper-V instance #{instance.to_str} has been removed.")
66
+ state.delete(:id)
67
+ end
68
+
69
+ private
70
+
71
+ def validate_vm_settings
72
+ return if config[:vm_switch]
73
+ config[:vm_switch] = (run_ps vm_default_switch_ps)['Name']
74
+ end
75
+
76
+ def kitchen_vm_path
77
+ @kitchen_vm_path ||= File.join(config[:kitchen_root], ".kitchen/#{instance.name}")
78
+ end
79
+
80
+ def differencing_disk_path
81
+ @differencing_disk_path ||= File.join(kitchen_vm_path, 'diff.vhd')
82
+ end
83
+
84
+ def parent_vhd_path
85
+ @parent_vhd_path ||= File.join(config[:parent_vhd_folder], config[:parent_vhd_name])
86
+ end
87
+
88
+ def vm_exists
89
+ info('Checking for existing virtual machine.')
90
+ return false unless @state.key?(:id) || @state[:id].nil?
91
+ existing_vm = run_ps ensure_vm_running_ps
92
+ info("Found an exising VM with an ID: #{existing_vm['Id']}")
93
+ return true unless existing_vm.nil? || existing_vm['Id'].nil?
94
+ #fail('Failed to start existing VM.')
95
+ end
96
+
97
+ def remove_differencing_disk
98
+ info("Removing the differencing disk for #{instance.name}.")
99
+ FileUtils.rm(differencing_disk_path)
100
+ info("Removed the differencing disk for #{instance.name}.")
101
+ end
102
+
103
+ def create_new_differencing_disk
104
+ return if File.exist? differencing_disk_path
105
+ info("Creating differencing disk for #{instance.name}.")
106
+ run_ps new_differencing_disk_ps
107
+ info("Created differencing disk for #{instance.name}.")
108
+ end
109
+
110
+ def remove_virtual_machine
111
+ info("Deleting virtual machine for #{instance.name}")
112
+ run_ps delete_vm_ps
113
+ info("Deleted virtual machine for #{instance.name}")
114
+ end
115
+
116
+ def create_virtual_machine
117
+ return if vm_exists
118
+ info("Creating virtual machine for #{instance.name}.")
119
+ new_vm_object = run_ps new_vm_ps
120
+ @state[:id] = new_vm_object['Id']
121
+ info("Created virtual machine for #{instance.name}.")
122
+ end
123
+
124
+ def update_state
125
+ vm_details
126
+ @state[:id] = @vm['Id']
127
+ @state[:hostname] = @vm['IpAddress']
128
+ @state[:vm_name] = @vm['Name']
129
+ @state[:password] = config[:password]
130
+ @state[:username] = config[:username]
131
+ end
132
+
133
+ def vm_details
134
+ run_ps set_vm_ipaddress_ps if config[:ip_address]
135
+ @vm = run_ps vm_details_ps
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +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.1.0'
21
+ end
22
+ end
@@ -0,0 +1,131 @@
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 powershell_64_bit
31
+ 'c:\windows\sysnative\windowspowershell\v1.0\powershell.exe'
32
+ end
33
+
34
+ def wrap_command(script)
35
+ base_script_path = File.join(File.dirname(__FILE__), '/../../../support/hyperv.ps1')
36
+ debug("Loading functions from #{base_script_path}")
37
+ new_script = ". #{base_script_path}; " << script
38
+ debug("Wrapped script: #{new_script}")
39
+ "#{powershell_64_bit} -encodedcommand #{encode_command new_script} -outputformat Text"
40
+ end
41
+
42
+ # Convenience method to run a powershell command locally.
43
+ #
44
+ # @param cmd [String] command to run locally
45
+ # @param options [Hash] options hash
46
+ # @see Kitchen::ShellOut.run_command
47
+ # @api private
48
+ def run_ps(cmd, options = {})
49
+ cmd = "echo #{cmd}" if config[:dry_run]
50
+ debug('Preparing to run: ')
51
+ debug(" #{cmd}")
52
+ wrapped_command = wrap_command cmd
53
+ execute_command wrapped_command, options
54
+ end
55
+
56
+ # rubocop:disable Metrics/AbcSize
57
+ def execute_command(cmd, options = {})
58
+ debug("#Local Command BEGIN (#{cmd})")
59
+ sh = Mixlib::ShellOut.new(cmd, options)
60
+ sh.run_command
61
+ debug("Local Command END #{Util.duration(sh.execution_time)}")
62
+ fail "Failed: #{sh.stderr}" if sh.error?
63
+ JSON.parse(sh.stdout) if sh.stdout.length > 2
64
+ end
65
+ # rubocop:enable Metrics/AbcSize
66
+
67
+ def new_differencing_disk_ps
68
+ <<-DIFF
69
+
70
+ New-DifferencingDisk -Path "#{differencing_disk_path}" -ParentPath "#{parent_vhd_path}"
71
+ DIFF
72
+ end
73
+
74
+ def ensure_vm_running_ps
75
+ <<-RUNNING
76
+
77
+ Assert-VmRunning -ID "#{@state[:id]}" | ConvertTo-Json
78
+ RUNNING
79
+ end
80
+
81
+ # rubocop:disable Metrics/MethodLength
82
+ def new_vm_ps
83
+ <<-NEWVM
84
+
85
+ $NewVMParams = @{
86
+ Generation = 1
87
+ MemoryStartupBytes = #{config[:memory_startup_bytes]}
88
+ Name = "#{instance.name}"
89
+ Path = "#{kitchen_vm_path}"
90
+ VHDPath = "#{differencing_disk_path}"
91
+ SwitchName = "#{config[:vm_switch]}"
92
+ ProcessorCount = #{config[:processor_count]}
93
+ }
94
+ New-KitchenVM @NewVMParams | ConvertTo-Json
95
+ NEWVM
96
+ end
97
+ # rubocop:enable Metrics/MethodLength
98
+
99
+ def vm_details_ps
100
+ <<-DETAILS
101
+
102
+ Get-VmDetail -id "#{@state[:id]}" | ConvertTo-Json
103
+ DETAILS
104
+ end
105
+
106
+ def delete_vm_ps
107
+ <<-REMOVE
108
+
109
+ $null = Get-VM -ID "#{@state[:id]}" |
110
+ Stop-VM -Force -TurnOff -PassThru |
111
+ Remove-VM -Force
112
+ REMOVE
113
+ end
114
+
115
+ def set_vm_ipaddress_ps
116
+ <<-VMIP
117
+
118
+ (Get-VM -id "#{@state[:id]}").NetworkAdapters |
119
+ Set-VMNetworkConfiguration -ipaddress "#{config[:ip_address]}" -subnet 255.255.255.0 |
120
+ ConvertTo-Json
121
+ VMIP
122
+ end
123
+
124
+ def vm_default_switch_ps
125
+ <<-VMSWITCH
126
+ Get-DefaultVMSwitch | ConvertTo-Json
127
+ VMSWITCH
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +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
@@ -0,0 +1,43 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2012, 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
+ gem "minitest"
20
+ gem "minitest-stub-const"
21
+
22
+ if ENV["CODECLIMATE_REPO_TOKEN"]
23
+ require "codeclimate-test-reporter"
24
+ CodeClimate::TestReporter.start
25
+ elsif ENV["COVERAGE"]
26
+ require "simplecov"
27
+ SimpleCov.profiles.define "gem" do
28
+ command_name "Specs"
29
+
30
+ add_filter ".gem/"
31
+ add_filter "/spec/"
32
+ add_filter "/lib/vendor/"
33
+
34
+ add_group "Libraries", "/lib/"
35
+ end
36
+ SimpleCov.start "gem"
37
+ end
38
+
39
+ require 'minitest'
40
+ require 'minitest/stub_const'
41
+ require "minitest/autorun"
42
+ require "mocha/setup"
43
+ require "tempfile"
@@ -0,0 +1,2 @@
1
+ . $PSScriptRoot\..\..\support\hyperv.ps1
2
+
@@ -0,0 +1,149 @@
1
+
2
+ $ProgressPreference = "SilentlyContinue"
3
+
4
+ <<<<<<< HEAD:lib/kitchen/support/hyperv.ps1
5
+ function new-differencingdisk
6
+ =======
7
+ function New-DifferencingDisk
8
+ >>>>>>> rubocop'd and some tests:support/hyperv.ps1
9
+ {
10
+ [cmdletbinding()]
11
+ param ([string[]]$Path, [string]$ParentPath)
12
+ if (-not (test-path $Path))
13
+ {
14
+ $null = new-vhd @psboundparameters -Differencing
15
+ }
16
+ }
17
+
18
+ function Assert-VmRunning
19
+ {
20
+ [cmdletbinding()]
21
+ param([string]$Id)
22
+
23
+ if ([string]::IsNullOrEmpty($ID))
24
+ {
25
+ $Output = [pscustomobject]@{Name = '';State =''}
26
+ }
27
+ else
28
+ {
29
+ $Output = Get-VM -Id $ID |
30
+ foreach {
31
+ if ($_.State -notlike 'Running')
32
+ {
33
+ $_ | start-vm -passthru
34
+ }
35
+ else
36
+ {
37
+ $_
38
+ }
39
+ } |
40
+ select Name, Id, State
41
+ }
42
+ $output
43
+ }
44
+
45
+ function New-KitchenVM
46
+ {
47
+ [cmdletbinding()]
48
+ param (
49
+ $Generation = 1,
50
+ $MemoryStartupBytes,
51
+ $Name,
52
+ $Path,
53
+ $VHDPath,
54
+ $SwitchName,
55
+ $ProcessorCount
56
+ )
57
+ $null = $psboundparameters.remove('ProcessorCount')
58
+ new-vm @psboundparameters |
59
+ Set-Vm -ProcessorCount $ProcessorCount -passthru |
60
+ Start-Vm -passthru |
61
+ foreach {
62
+ $vm = $_
63
+ do {
64
+ start-sleep -seconds 2
65
+ } while ($vm.state -notlike 'Running')
66
+ $vm
67
+ } |
68
+ select Name, Id, State
69
+ }
70
+
71
+ function Get-VmIP($vm)
72
+ {
73
+ $vm.networkadapters.ipaddresses |
74
+ where {$_ -match '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'} |
75
+ select -first 1
76
+ }
77
+
78
+ Function Set-VMNetworkConfiguration
79
+ {
80
+ [CmdletBinding()]
81
+ Param (
82
+ [parameter(valuefrompipeline)]
83
+ [object]$NetworkAdapter,
84
+ [String[]]$IPAddress=@(),
85
+ [String[]]$Subnet=@()
86
+ )
87
+
88
+ $VM = Get-WmiObject -Namespace 'root\virtualization\v2' -Class 'Msvm_ComputerSystem' | Where-Object { $_.ElementName -eq $NetworkAdapter.VMName }
89
+ $VMSettings = $vm.GetRelated('Msvm_VirtualSystemSettingData') | Where-Object { $_.VirtualSystemType -eq 'Microsoft:Hyper-V:System:Realized' }
90
+ $VMNetAdapters = $VMSettings.GetRelated('Msvm_SyntheticEthernetPortSettingData')
91
+
92
+ $NetworkSettings = @()
93
+ foreach ($NetAdapter in $VMNetAdapters) {
94
+ if ($NetAdapter.Address -eq $NetworkAdapter.MacAddress) {
95
+ $NetworkSettings = $NetworkSettings + $NetAdapter.GetRelated("Msvm_GuestNetworkAdapterConfiguration")
96
+ }
97
+ }
98
+
99
+ $NetworkSettings[0].IPAddresses = $IPAddress
100
+ $NetworkSettings[0].Subnets = $Subnet
101
+ $NetworkSettings[0].ProtocolIFType = 4096
102
+ $NetworkSettings[0].DHCPEnabled = $false
103
+
104
+
105
+ $Service = Get-WmiObject -Class "Msvm_VirtualSystemManagementService" -Namespace "root\virtualization\v2"
106
+ $setIP = $Service.SetGuestNetworkAdapterConfiguration($VM, $NetworkSettings[0].GetText(1))
107
+
108
+ if ($setip.ReturnValue -eq 4096) {
109
+ $job=[WMI]$setip.job
110
+
111
+ while ($job.JobState -eq 3 -or $job.JobState -eq 4) {
112
+ start-sleep 1
113
+ $job=[WMI]$setip.job
114
+ }
115
+
116
+ if ($job.JobState -ne 7) {
117
+ $job.GetError()
118
+ }
119
+ }
120
+ (Get-VM -id $NetworkAdapter.VmId).NetworkAdapter | select Name, IpAddress
121
+ }
122
+
123
+ function Get-VmDetail
124
+ {
125
+ [cmdletbinding()]
126
+ param($Id)
127
+
128
+ get-vm -id $Id |
129
+ foreach {
130
+ $vm = $_
131
+ do {
132
+ start-sleep -seconds 1
133
+ } while (-not (Get-VmIP $vm))
134
+
135
+ [pscustomobject]@{
136
+ Name = $vm.name
137
+ Id = $vm.ID
138
+ IpAddress = (Get-VmIP $vm)
139
+ }
140
+ }
141
+ <<<<<<< HEAD:lib/kitchen/support/hyperv.ps1
142
+ =======
143
+ }
144
+
145
+ function Get-DefaultVMSwitch
146
+ {
147
+ Get-VMSwitch | Select -First 1
148
+ >>>>>>> rubocop'd and some tests:support/hyperv.ps1
149
+ }
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kitchen-hyperv
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Steven Murawski
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.10'
55
+ - !ruby/object:Gem::Dependency
56
+ name: test-kitchen
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.4'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.4'
69
+ description: Hyper-V Driver for Test-Kitchen
70
+ email:
71
+ - steven.murawski@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".cane"
77
+ - ".gitignore"
78
+ - ".rubocop.yml"
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - kitchen-hyperv.gemspec
84
+ - lib/kitchen/driver/hyperv.rb
85
+ - lib/kitchen/driver/hyperv_version.rb
86
+ - lib/kitchen/driver/powershell.rb
87
+ - spec/kitchen/driver/hyperv_spec.rb
88
+ - spec/spec_helper.rb
89
+ - spec/support/hyperv.Tests.ps1
90
+ - support/hyperv.ps1
91
+ homepage: ''
92
+ licenses:
93
+ - Apache 2
94
+ metadata: {}
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubyforge_project:
111
+ rubygems_version: 2.4.4
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: Hyper-V Driver for Test-Kitchen
115
+ test_files:
116
+ - spec/kitchen/driver/hyperv_spec.rb
117
+ - spec/spec_helper.rb
118
+ - spec/support/hyperv.Tests.ps1
119
+ has_rdoc: