kitchen-vmm 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.cane +2 -0
- data/.gitignore +15 -0
- data/.rubocop.yml +5 -0
- data/.travis.yml +14 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +228 -0
- data/Rakefile +52 -0
- data/kitchen-vmm.gemspec +31 -0
- data/lib/kitchen/driver/vmm.rb +102 -0
- data/lib/kitchen/driver/vmm_utils.rb +84 -0
- data/lib/kitchen/driver/vmm_version.rb +7 -0
- data/support/delete_vm.ps1 +35 -0
- data/support/import_vm.ps1 +165 -0
- data/support/utils/manage_credentials.ps1 +26 -0
- data/support/utils/manage_trusted_hosts.ps1 +28 -0
- data/support/utils/vmm_executor.ps1 +43 -0
- data/support/utils/write_messages.ps1 +20 -0
- metadata +175 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YjJiM2EyYmI2YjE1MTgzYmRkM2JkNWY2NjVkMDlmNTM5OTc2OTQzNw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
OTgxMzBkZmYyMWQ2MDM1ZTc1N2I3NTAzOWE1MTQ5NTIyMzViYjUxYg==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YTNkMzUyOTFjODM4MmVlMjYzZDY4MjlmNmE1YjFjMWYyYTVmMDhjOTk3NjUx
|
10
|
+
YWU2NjcwOTJiMDBmYjhlMmZhYjgzMjQzN2ZkMTVhOGRhODFmOTAxNGE2ZjQz
|
11
|
+
OTlkZTVhY2E3ODdjMGFlNWFjYzE5MWVmYmM2MmVmZTllNmYxM2E=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MWI1M2NmNmE0ODQ4OWM5NzM4NmQwM2QyY2UyNzQ0YjZkNjNiM2MzNGRkMzlm
|
14
|
+
NWI0MzA1ZGFjNzM4ZDQ4NjdjYjM1Nzc3NDA4NzU1MTM2YTg1MjQ3YTk3MWYw
|
15
|
+
MzBkZDViNDk4NTUwMDkxYTY5YjgwMjM0NjliNTQ5ZDRiZWE0NmY=
|
data/.cane
ADDED
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 2.0.0
|
4
|
+
bundler_args: --without doc guard --jobs 7
|
5
|
+
script: bundle exec rake build
|
6
|
+
deploy:
|
7
|
+
provider: rubygems
|
8
|
+
api_key:
|
9
|
+
secure: j4qKRcVgSpULZXlSyGSt5WmHTCazXmH1uNNcfpUioIMOZkceh7CWspMps3FWSPIbINqLoSfzK4hJbUcnoqSZ79ho8NBbcNvqTIJXxFoYbhTgTlUwdNovgto4WmqwEYDSWp+ShryLqLkRY6WGFFUu2ve4eRum1akQcaxkQC1vjcKsQXUDFCY8qW6unsFQivV3YMX+baTHcOpB/YyEqwkHq5N6173U7eM0Rmu5F39PIKovb/wBLYomuV7vDH7kGvxernVguUNC0azgLe9j1lTQT1bkmn78pCwb9PYeW8xkkTWW0DSZf5n9TSG1jhECGUkmeNJbMBpFioApvYfEoyKq58vPPJ5eyjz5rvOshfwIefzOgdS6RoHMfWzA1StzPj3iQwnhow70vhU4vZJ3HI8pTyCv2szhItdBL6Z4Hc90KrXKX6HaBuRHw2wv48+tvoKU3hnguswrYer7nSOSfTKMxMHTNoevlieRNX/3Suh7/8laV1eobYRv7yUSkGpFdeT+8FqlSBJVG/A6fyct/DqOhMLV48y8Rc2pqDTdVJ638LAwdcUhvvqYe04i5Zxr7Qa0Wi89bHLRhR0R3o5pvgVAJt3wjVKKHz0kuN1cbP60B4d/Xmp8lQRL0MADAVfaiSJvI/vDMCt48/qBzRe4IQBMwI4iMCwDZ56DTyXKaGO08x8=
|
10
|
+
gem: kitchen-vmm
|
11
|
+
on:
|
12
|
+
tags: true
|
13
|
+
repo: jarig/kitchen-vmm
|
14
|
+
all_branches: true
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Jaroslav
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,228 @@
|
|
1
|
+
# Kitchen::VMM
|
2
|
+
|
3
|
+
|Travis CI|Gem|
|
4
|
+
|-----|-----|
|
5
|
+
| [![Build Status](https://travis-ci.org/jarig/kitchen-vmm.svg?branch=master)](https://travis-ci.org/jarig/kitchen-vmm)|[![Gem Version](https://badge.fury.io/rb/kitchen-vmm.svg)](http://badge.fury.io/rb/kitchen-vmm)|
|
6
|
+
|
7
|
+
Supports: Windows, Linux
|
8
|
+
|
9
|
+
Virtual Machine Management plugin for Kitchen.
|
10
|
+
|
11
|
+
This provider will allow you to create VMs in the remote Virtual Machine Manager via Test Kitchen.
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Install kitchen-vmm gem
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
chef gem 'kitchen-vmm'
|
19
|
+
```
|
20
|
+
|
21
|
+
## Prerequisites
|
22
|
+
|
23
|
+
1. You should have template in your VMM which has following things setup:
|
24
|
+
- WinRM and firewall configured, using:
|
25
|
+
```
|
26
|
+
winrm quickconfig
|
27
|
+
```
|
28
|
+
- Either domain or local user with admin rights.
|
29
|
+
You can specify its creds using
|
30
|
+
(either in cookbook .kitchen.yml or in $HOME/.kitchen/config.yml):
|
31
|
+
```yaml
|
32
|
+
transport:
|
33
|
+
name: winrm
|
34
|
+
username: <username>
|
35
|
+
password: <password>
|
36
|
+
```
|
37
|
+
- Once VM created in VMM it should automatically get IP assigned, as well as it should be directly accessible from your machine.
|
38
|
+
2. Run kitchen commands under **Administrator** (in admin shell).
|
39
|
+
|
40
|
+
## Usage
|
41
|
+
|
42
|
+
In the .kitchen.yml
|
43
|
+
|
44
|
+
### Configure Driver
|
45
|
+
|
46
|
+
Globally
|
47
|
+
```yaml
|
48
|
+
driver:
|
49
|
+
name: vmm
|
50
|
+
vm_template_name: default-template
|
51
|
+
vm_host_group_name: default-group
|
52
|
+
```
|
53
|
+
|
54
|
+
Or per platform
|
55
|
+
```yaml
|
56
|
+
platforms:
|
57
|
+
- name: platform1
|
58
|
+
driver:
|
59
|
+
name: vmm
|
60
|
+
vm_template_name: 'overidden-template'
|
61
|
+
vm_host_group_name: overidden-group
|
62
|
+
```
|
63
|
+
|
64
|
+
### Configure Transport
|
65
|
+
|
66
|
+
In case you need to create both Linux and Windows machines, then different transport types have to be used(ssh for linux and winrm for windows).
|
67
|
+
For easier maintenance and cleaner configuration you can create global kitchen configuration under $HOME/<username>/.kitchen/config.yml with following contents:
|
68
|
+
|
69
|
+
```yaml
|
70
|
+
<% WINRM_USERNAME = 'winrm_user' %>
|
71
|
+
<% WINRM_PASSWORD = 'winrm_dassword' %>
|
72
|
+
|
73
|
+
# default transport settings
|
74
|
+
transport:
|
75
|
+
name: ssh
|
76
|
+
username: ssh_user
|
77
|
+
ssh_key: <path_to_key>
|
78
|
+
# winrm related settings that do not clash with ssh ones can also go here
|
79
|
+
# example: winrm_transport
|
80
|
+
```
|
81
|
+
|
82
|
+
Then in your kitchen.yml specify transport either for platform or suite
|
83
|
+
```yaml
|
84
|
+
suites:
|
85
|
+
- name: windows-basic
|
86
|
+
run_list:
|
87
|
+
- recipe[windows-basic::default]
|
88
|
+
transport:
|
89
|
+
name: winrm
|
90
|
+
username: <%= WINRM_USERNAME %>
|
91
|
+
password: <%= WINRM_PASSWORD %>
|
92
|
+
```
|
93
|
+
|
94
|
+
### Required parameters:
|
95
|
+
|
96
|
+
* #### vm_template_name
|
97
|
+
|
98
|
+
VMM template name that will be used for VM creation.
|
99
|
+
|
100
|
+
```yaml
|
101
|
+
driver_config:
|
102
|
+
...
|
103
|
+
vm_template_name: vagrant-template-w8.1-64
|
104
|
+
```
|
105
|
+
|
106
|
+
* #### vm_host_group_name
|
107
|
+
|
108
|
+
VMM host group where VM will be placed.
|
109
|
+
NOTE: Your template or *vm_hardware_profile* should match it as well.
|
110
|
+
|
111
|
+
```yaml
|
112
|
+
driver_config:
|
113
|
+
...
|
114
|
+
vm_host_group_name: 'Host-Group-Name'
|
115
|
+
```
|
116
|
+
|
117
|
+
* #### vmm_server_address
|
118
|
+
|
119
|
+
IP/Hostname of the VMM server where VMs are going to be created.
|
120
|
+
```yaml
|
121
|
+
driver_config:
|
122
|
+
...
|
123
|
+
vmm_server_address: '192.124.125.10'
|
124
|
+
```
|
125
|
+
|
126
|
+
### Optional parameters:
|
127
|
+
|
128
|
+
* #### vm_name
|
129
|
+
|
130
|
+
Specify name of a VM that is going to be created. Default is Kitchen instance name.
|
131
|
+
If VM with such name already exists driver might get random number appended to it.
|
132
|
+
|
133
|
+
```yaml
|
134
|
+
driver_config:
|
135
|
+
...
|
136
|
+
vm_name: 'my-vm-in-vmm'
|
137
|
+
```
|
138
|
+
|
139
|
+
* #### vm_hardware_profile
|
140
|
+
|
141
|
+
Specify alternate HW profile that should be used instead of the one provided in your original template.
|
142
|
+
|
143
|
+
```yaml
|
144
|
+
driver_config:
|
145
|
+
...
|
146
|
+
vm_hardware_profile: 'TestHW-8core-8gb'
|
147
|
+
```
|
148
|
+
|
149
|
+
* #### proxy_server_address
|
150
|
+
|
151
|
+
If your local machine do not have direct access to the machine that hosts VMM, but you have proxy server(jump box) you can specify its IP in *proxy_server_address* property.
|
152
|
+
|
153
|
+
```yaml
|
154
|
+
driver_config:
|
155
|
+
...
|
156
|
+
proxy_server_address: 'my-proxy-to-vmm'
|
157
|
+
```
|
158
|
+
|
159
|
+
* #### ad_server
|
160
|
+
|
161
|
+
You can tell the provider to move your VM under some particular OU once it's created.
|
162
|
+
|
163
|
+
URL of AD server. Can be derived by running ```echo %LOGONSERVER%``` command in CMD of the VM environment.
|
164
|
+
|
165
|
+
Example:
|
166
|
+
```yaml
|
167
|
+
driver_config:
|
168
|
+
...
|
169
|
+
ad_server: 'my-ad-server.some.domain.local'
|
170
|
+
```
|
171
|
+
|
172
|
+
* #### ad_source_path
|
173
|
+
|
174
|
+
Base DN container where VM appears(and it will be moved from) once it's created.
|
175
|
+
Example:
|
176
|
+
```yaml
|
177
|
+
driver_config:
|
178
|
+
...
|
179
|
+
ad_source_path: 'CN=Computers,DC=some,DC=domain,DC=local'
|
180
|
+
```
|
181
|
+
|
182
|
+
* #### ad_target_path
|
183
|
+
|
184
|
+
New AD path where VM should be moved to.
|
185
|
+
Example:
|
186
|
+
```yaml
|
187
|
+
driver_config:
|
188
|
+
...
|
189
|
+
ad_target_path: 'OU=Vagrant,OU=Chef-Nodes,DC=some,DC=domain,DC=local'
|
190
|
+
```
|
191
|
+
|
192
|
+
|
193
|
+
## Troubleshooting
|
194
|
+
|
195
|
+
### Authorization failure
|
196
|
+
|
197
|
+
Check that winrm is configured properly in the VM, if username/password is local then ensure you've set winrm transport to plaintext for kitchen.
|
198
|
+
```yaml
|
199
|
+
transport:
|
200
|
+
name: winrm
|
201
|
+
...
|
202
|
+
winrm_transport: plaintext
|
203
|
+
```
|
204
|
+
and enable basic auth and unencrypted connection in a VM.
|
205
|
+
```
|
206
|
+
winrm set winrm/config/service/auth @{Basic="true"}
|
207
|
+
winrm set winrm/config/service @{AllowUnencrypted="true"}
|
208
|
+
```
|
209
|
+
and on your local machine
|
210
|
+
```
|
211
|
+
winrm set winrm/config/client/auth @{Basic="true"}
|
212
|
+
```
|
213
|
+
|
214
|
+
### Unencrypted traffic is currently disabled in the client configuration
|
215
|
+
|
216
|
+
Run following command on your machine as well:
|
217
|
+
```
|
218
|
+
winrm set winrm/config/service @{AllowUnencrypted="true"}
|
219
|
+
```
|
220
|
+
|
221
|
+
|
222
|
+
## Contributing
|
223
|
+
|
224
|
+
1. Fork it ( https://github.com/[my-github-username]/kitchen-vmm/fork )
|
225
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
226
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
227
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
228
|
+
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]
|
data/kitchen-vmm.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
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/vmm_version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "kitchen-vmm"
|
9
|
+
spec.version = Kitchen::Driver::VMM_VERSION
|
10
|
+
spec.authors = ["Jaroslav Gorjatsev"]
|
11
|
+
spec.email = ["gjarik@gmail.com"]
|
12
|
+
spec.summary = 'Virtual Machine Manager Driver for Test-Kitchen'
|
13
|
+
spec.description = 'Virtual Machine Manager Driver for Test-Kitchen'
|
14
|
+
spec.homepage = "https://github.com/jarig/kitchen-vmm"
|
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
|
+
spec.add_development_dependency "cane"
|
26
|
+
spec.add_development_dependency "finstyle"
|
27
|
+
spec.add_development_dependency "rubocop"
|
28
|
+
spec.add_development_dependency "yard"
|
29
|
+
|
30
|
+
spec.add_dependency "test-kitchen", "~> 1.4"
|
31
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'kitchen'
|
2
|
+
require 'kitchen/driver'
|
3
|
+
require 'kitchen/driver/vmm_version'
|
4
|
+
require 'kitchen/driver/vmm_utils'
|
5
|
+
require 'mixlib/shellout'
|
6
|
+
require 'fileutils'
|
7
|
+
require 'JSON'
|
8
|
+
|
9
|
+
module Kitchen
|
10
|
+
|
11
|
+
module Driver
|
12
|
+
|
13
|
+
# Driver for VMM
|
14
|
+
class Vmm < Kitchen::Driver::Base
|
15
|
+
|
16
|
+
kitchen_driver_api_version 2
|
17
|
+
plugin_version Kitchen::Driver::VMM_VERSION
|
18
|
+
|
19
|
+
default_config :vm_template_name
|
20
|
+
default_config :vm_host_group_name
|
21
|
+
default_config :vmm_server_address
|
22
|
+
default_config :vm_name, nil
|
23
|
+
default_config :vm_hardware_profile, ''
|
24
|
+
default_config :proxy_server_address, ''
|
25
|
+
default_config :ad_server, ''
|
26
|
+
default_config :ad_source_path, ''
|
27
|
+
default_config :ad_target_path, ''
|
28
|
+
|
29
|
+
def create(state)
|
30
|
+
@state = state
|
31
|
+
validate_vm_settings
|
32
|
+
create_virtual_machine
|
33
|
+
info("VM instance #{instance.to_str} created.")
|
34
|
+
end
|
35
|
+
|
36
|
+
def destroy(state)
|
37
|
+
@state = state
|
38
|
+
instance.transport.connection(state).close
|
39
|
+
remove_virtual_machine
|
40
|
+
info("The VM instance #{instance.to_str} has been removed.")
|
41
|
+
state.delete(:id)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
include Kitchen::Driver::VMMUtils
|
47
|
+
|
48
|
+
def validate_vm_settings
|
49
|
+
raise "Missing vmm_server_address" unless config[:vmm_server_address]
|
50
|
+
end
|
51
|
+
|
52
|
+
def kitchen_vm_path
|
53
|
+
@kitchen_vm_path ||= File.join(config[:kitchen_root], ".kitchen/#{instance.name}")
|
54
|
+
end
|
55
|
+
|
56
|
+
def remove_virtual_machine
|
57
|
+
info("Deleting virtual machine for #{instance.name}")
|
58
|
+
options = {
|
59
|
+
vmm_server_address: config[:vmm_server_address],
|
60
|
+
proxy_server_address: config[:proxy_server_address],
|
61
|
+
vm_id: @state[:id]
|
62
|
+
}
|
63
|
+
execute('delete_vm.ps1', options)
|
64
|
+
info("Deleted virtual machine for #{instance.name}")
|
65
|
+
end
|
66
|
+
|
67
|
+
def vm_exists
|
68
|
+
false
|
69
|
+
end
|
70
|
+
|
71
|
+
def create_virtual_machine
|
72
|
+
return if vm_exists
|
73
|
+
info("Creating virtual machine for #{instance.name}.")
|
74
|
+
options = {
|
75
|
+
vmm_server_address: config[:vmm_server_address],
|
76
|
+
proxy_server_address: config[:proxy_server_address],
|
77
|
+
vm_hardware_profile: config[:vm_hardware_profile],
|
78
|
+
vm_name: config[:vm_name] || instance.name,
|
79
|
+
vm_template_name: config[:vm_template_name],
|
80
|
+
vm_host_group_name: config[:vm_host_group_name],
|
81
|
+
ad_server: config[:ad_server],
|
82
|
+
ad_source_path: config[:ad_source_path],
|
83
|
+
ad_target_path: config[:ad_target_path]
|
84
|
+
}
|
85
|
+
|
86
|
+
#
|
87
|
+
info("Creating and registering VM in the VMM (#{options[:vmm_server_address]})...")
|
88
|
+
if options[:ad_server] && options[:ad_source_path] && options[:ad_target_path]
|
89
|
+
info(" ..and moving it under #{options[:ad_target_path]} after it's created.")
|
90
|
+
end
|
91
|
+
vm = execute('import_vm.ps1', options)
|
92
|
+
info("Successfully created the VM with name: #{vm['name']}")
|
93
|
+
@state[:id] = vm['id']
|
94
|
+
@state[:hostname] = vm['hostname']
|
95
|
+
@state[:vm_name] = vm['name']
|
96
|
+
|
97
|
+
info("Created virtual machine for #{instance.name}.")
|
98
|
+
end
|
99
|
+
|
100
|
+
end # class VMM
|
101
|
+
end # module Driver
|
102
|
+
end # module Kitchen
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Kitchen
|
2
|
+
module Driver
|
3
|
+
module VMMUtils
|
4
|
+
|
5
|
+
ERROR_REGEXP = /===Begin-Error===(.+?)===End-Error===/m
|
6
|
+
OUTPUT_REGEXP = /===Begin-Output===(.+?)===End-Output===/m
|
7
|
+
|
8
|
+
def execute(path, options)
|
9
|
+
r = execute_powershell(path, options)
|
10
|
+
if r.error?
|
11
|
+
raise ("Powershell failed, #{path}:#{r.stderr}")
|
12
|
+
end
|
13
|
+
|
14
|
+
# We only want unix-style line endings within Vagrant
|
15
|
+
r.stdout.gsub!("\r\n", "\n")
|
16
|
+
r.stderr.gsub!("\r\n", "\n")
|
17
|
+
|
18
|
+
error_match = ERROR_REGEXP.match(r.stdout)
|
19
|
+
output_match = OUTPUT_REGEXP.match(r.stdout)
|
20
|
+
|
21
|
+
if error_match
|
22
|
+
data = JSON.parse(error_match[1])
|
23
|
+
|
24
|
+
# We have some error data.
|
25
|
+
raise "#{path}:#{data["error"]}"
|
26
|
+
end
|
27
|
+
|
28
|
+
# Nothing
|
29
|
+
return nil if !output_match
|
30
|
+
return JSON.parse(output_match[1])
|
31
|
+
end
|
32
|
+
|
33
|
+
def execute_powershell(path, options = {})
|
34
|
+
lib_path = Pathname.new(File.expand_path("../../../../support", __FILE__))
|
35
|
+
script_path = lib_path.join(path).to_s.gsub("/", "\\")
|
36
|
+
ps_options = ''
|
37
|
+
options.each do |key, value|
|
38
|
+
unless value.nil?
|
39
|
+
ps_options += " -#{key} \"#{value}\""
|
40
|
+
end
|
41
|
+
end
|
42
|
+
#
|
43
|
+
stdout_stream_reader = StreamReader.new do |line|
|
44
|
+
info(line)
|
45
|
+
end
|
46
|
+
ps_run = Mixlib::ShellOut.new("powershell.exe -File #{script_path} #{ps_options} -ErrorAction Stop")
|
47
|
+
debug("Command: #{ps_run.command}")
|
48
|
+
ps_run.live_stdout = stdout_stream_reader
|
49
|
+
ps_run.run_command
|
50
|
+
return ps_run
|
51
|
+
end
|
52
|
+
|
53
|
+
# for powershell stdout read
|
54
|
+
class StreamReader
|
55
|
+
require 'stringio'
|
56
|
+
|
57
|
+
def initialize(&block)
|
58
|
+
@block = block
|
59
|
+
@buffer = StringIO.new
|
60
|
+
@buffer.sync = true if @buffer.respond_to?(:sync)
|
61
|
+
end
|
62
|
+
|
63
|
+
def <<(chunk)
|
64
|
+
overflow = ''
|
65
|
+
|
66
|
+
@buffer.write(chunk)
|
67
|
+
@buffer.rewind
|
68
|
+
|
69
|
+
@buffer.each_line do |line|
|
70
|
+
if line.match(/\r?\n/)
|
71
|
+
@block.call(line.strip)
|
72
|
+
else
|
73
|
+
overflow = line
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
@buffer.truncate(@buffer.rewind)
|
78
|
+
@buffer.write(overflow)
|
79
|
+
end
|
80
|
+
end # StreamReader
|
81
|
+
|
82
|
+
end # module VMMUtils
|
83
|
+
end # module Driver
|
84
|
+
end # module Kitchen
|
@@ -0,0 +1,35 @@
|
|
1
|
+
Param(
|
2
|
+
[Parameter(Mandatory=$true)]
|
3
|
+
[string]$vm_id,
|
4
|
+
[Parameter(Mandatory=$true)]
|
5
|
+
[string]$vmm_server_address,
|
6
|
+
[string]$proxy_server_address=$null
|
7
|
+
)
|
8
|
+
|
9
|
+
|
10
|
+
# Include the following modules
|
11
|
+
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
|
12
|
+
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
|
13
|
+
. ([System.IO.Path]::Combine($Dir, "utils\vmm_executor.ps1"))
|
14
|
+
|
15
|
+
|
16
|
+
$script_block = {
|
17
|
+
# external vars
|
18
|
+
$vm_id = $using:vm_id
|
19
|
+
|
20
|
+
# Get VM
|
21
|
+
$vm = Get-SCVirtualMachine -ID $vm_id -ErrorAction Ignore
|
22
|
+
if ( $vm )
|
23
|
+
{
|
24
|
+
if ( $vm.status -eq 'Running' )
|
25
|
+
{
|
26
|
+
$res = Stop-VM $vm
|
27
|
+
}
|
28
|
+
$res = Remove-VM $vm
|
29
|
+
} else
|
30
|
+
{
|
31
|
+
Write-Host "VM do not exists or not found: $vm_id"
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
execute $script_block $vmm_server_address $proxy_server_address
|
@@ -0,0 +1,165 @@
|
|
1
|
+
Param(
|
2
|
+
[Parameter(Mandatory=$true)]
|
3
|
+
[string]$vm_name,
|
4
|
+
[Parameter(Mandatory=$true)]
|
5
|
+
[string]$vmm_server_address,
|
6
|
+
[Parameter(Mandatory=$true)]
|
7
|
+
[string]$vm_template_name,
|
8
|
+
[Parameter(Mandatory=$true)]
|
9
|
+
[string]$vm_host_group_name,
|
10
|
+
[string]$vm_hardware_profile=$null,
|
11
|
+
[string]$proxy_server_address=$null,
|
12
|
+
[string]$ad_server=$null,
|
13
|
+
[string]$ad_source_path=$null,
|
14
|
+
[string]$ad_target_path=$null
|
15
|
+
)
|
16
|
+
|
17
|
+
# Include the following modules
|
18
|
+
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
|
19
|
+
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
|
20
|
+
. ([System.IO.Path]::Combine($Dir, "utils\vmm_executor.ps1"))
|
21
|
+
|
22
|
+
|
23
|
+
$script_block = {
|
24
|
+
# external vars
|
25
|
+
$vm_name = $using:vm_name
|
26
|
+
$vm_host_group_name = $using:vm_host_group_name
|
27
|
+
$server_address = $using:vmm_server_address
|
28
|
+
$vm_template_name = $using:vm_template_name
|
29
|
+
$vm_hardware_profile_name = $using:vm_hardware_profile
|
30
|
+
$ad_server = $using:ad_server
|
31
|
+
$ad_source_path = $using:ad_source_path
|
32
|
+
$ad_target_path = $using:ad_target_path
|
33
|
+
|
34
|
+
$description = "VM created by chef test-kitchen for testing purposes"
|
35
|
+
$MinFreeSpaceGB = 300 #
|
36
|
+
|
37
|
+
$domain_name = $null
|
38
|
+
if ( $ad_source_path )
|
39
|
+
{
|
40
|
+
$domain_name = $($ad_source_path.split(",")|Where {$_.Contains("DC")}| ForEach-Object { $_.replace("DC=", "") }) -join "."
|
41
|
+
}
|
42
|
+
# Truncate vm name to 15 chars due to windows limitation
|
43
|
+
$vm_name = $vm_name.substring(0, [math]::Min(15, $vm_name.length))
|
44
|
+
|
45
|
+
# get VM Template object
|
46
|
+
$VMTemplate = Get-SCVMTemplate -Name $vm_template_name
|
47
|
+
# get host group
|
48
|
+
$VMHostGroup = Get-VMHostGroup -Name $vm_host_group_name
|
49
|
+
#
|
50
|
+
Write-Host "Creating VM from template $vm_template_name"
|
51
|
+
|
52
|
+
$tries = 10
|
53
|
+
while ( $tries -gt 0 ) {
|
54
|
+
$vm = Get-SCVirtualMachine -Name $vm_name
|
55
|
+
if ( $vm -eq $null ) {
|
56
|
+
break
|
57
|
+
} else {
|
58
|
+
$vm_name = $vm_name.substring(0, [math]::Min(14, $vm_name.length)) + $(Get-Random -Minimum 0 -Maximum 10)
|
59
|
+
}
|
60
|
+
$tries -= 1
|
61
|
+
}
|
62
|
+
if ( $vm -eq $null )
|
63
|
+
{
|
64
|
+
# Get and sort the host ratings for all the hosts in the host group.
|
65
|
+
# select host which has rating > 0
|
66
|
+
$hRatingHashParams = @{VMTemplate=$VMTemplate;
|
67
|
+
DiskSpaceGB=$MinFreeSpaceGB;
|
68
|
+
VMName=$vm_name;
|
69
|
+
VMHostGroup=$VMHostGroup;
|
70
|
+
}
|
71
|
+
|
72
|
+
if ( $vm_hardware_profile_name )
|
73
|
+
{
|
74
|
+
$vm_hardware_profile = Get-SCHardwareProfile | where {$_.Name -eq $vm_hardware_profile_name}
|
75
|
+
Write-host "Applying hardware profile: $vm_hardware_profile_name"
|
76
|
+
$VMTemplate = New-SCVMTemplate -Name "Temporary Template$([guid]::NewGuid())" -VMTemplate $VMTemplate -HardwareProfile $vm_hardware_profile
|
77
|
+
}
|
78
|
+
|
79
|
+
$VMHost = $null
|
80
|
+
$HostRatings = @(Get-SCVMHostRating @hRatingHashParams | Sort-Object -property Rating -descending)
|
81
|
+
If($HostRatings.Count -eq 0) { throw "No hosts meet the requirements." }
|
82
|
+
$VMHost = $HostRatings[0].VMHost
|
83
|
+
|
84
|
+
# If there is at least one host that will support the virtual machine, create the virtual machine on the highest-rated host.
|
85
|
+
If ($VMHost -ne $null )
|
86
|
+
{
|
87
|
+
# get placement path
|
88
|
+
$path = $($VMHost.DiskVolumes | where { $_.IsAvailableForPlacement -eq $True } | Sort-Object -Property FreeSpace -Descending)[0]
|
89
|
+
Write-Host "----- Creating VM ----"
|
90
|
+
Write-Host "Host: $VMHost, $($VMHost.CPUManufacturer) $($VMHost.Rank)"
|
91
|
+
Write-host "Placement path: $($path.Name), Free space - $($path.FreeSpace/1024/1024/1024) GB"
|
92
|
+
Write-Host "Name: $vm_name"
|
93
|
+
Write-Host "----- ----------- ----"
|
94
|
+
# Create the virtual machine.
|
95
|
+
$vmCreateParams = @{Name=$vm_name;
|
96
|
+
Path=$path.Name;
|
97
|
+
VMHost = $VMHost;
|
98
|
+
VMTemplate=$VMTemplate;
|
99
|
+
Description=$description;
|
100
|
+
ComputerName=$vm_name;
|
101
|
+
BlockDynamicOptimization=$false;
|
102
|
+
ReturnImmediately = $false; AnswerFile = $null;
|
103
|
+
StartAction = "NeverAutoTurnOnVM";
|
104
|
+
StopAction = "TurnOffVM";
|
105
|
+
StartVM=$true;
|
106
|
+
ErrorAction="stop";
|
107
|
+
}
|
108
|
+
|
109
|
+
$vm = New-SCVirtualMachine @vmCreateParams
|
110
|
+
} else {
|
111
|
+
Write-Error "Cannot find suitable host for the VM."
|
112
|
+
}
|
113
|
+
} else {
|
114
|
+
Write-Warning "Machine $vm_name already exists on host $($vm.VMHost.Name)"
|
115
|
+
}
|
116
|
+
Write-Host "Machine created."
|
117
|
+
# try to move it in AD
|
118
|
+
try
|
119
|
+
{
|
120
|
+
# move it to under AD path if required
|
121
|
+
if ($ad_target_path -ne $null -and $ad_source_path -ne $null -and $ad_server -ne $null)
|
122
|
+
{
|
123
|
+
Write-host "Moving it AD under $ad_target_path"
|
124
|
+
$cred_param = @{}
|
125
|
+
if ($proxy_credential)
|
126
|
+
{
|
127
|
+
# if proxy used to overcome credssp auth
|
128
|
+
$cred_param["Credential"] = $proxy_credential
|
129
|
+
}
|
130
|
+
$ad_res = Get-ADComputer -Identity:"CN=$vm_name,$ad_source_path" -Server:$ad_server -ErrorAction Ignore @cred_param
|
131
|
+
if ( $ad_res -ne $null )
|
132
|
+
{
|
133
|
+
Move-ADObject -Identity:"CN=$vm_name,$ad_source_path" -TargetPath:$ad_target_path -Server:$ad_server @cred_param
|
134
|
+
}
|
135
|
+
}
|
136
|
+
} catch
|
137
|
+
{
|
138
|
+
Write-Warning "Couldn't move under specified OU: $_"
|
139
|
+
}
|
140
|
+
|
141
|
+
$fqdn = $vm.ComputerNameString
|
142
|
+
if ( ! $fqdn.contains($domain_name) )
|
143
|
+
{
|
144
|
+
# Linux machines do not always set domain name propery for example
|
145
|
+
$fqdn = "$fqdn.$domain_name"
|
146
|
+
}
|
147
|
+
|
148
|
+
# return vm object
|
149
|
+
@{
|
150
|
+
vm = $vm
|
151
|
+
fqdn = $fqdn
|
152
|
+
ip = $ip
|
153
|
+
}
|
154
|
+
}
|
155
|
+
|
156
|
+
$result = execute $script_block $vmm_server_address $proxy_server_address
|
157
|
+
|
158
|
+
$resultHash = @{
|
159
|
+
hostname = $result.fqdn
|
160
|
+
name = $result.vm.Name
|
161
|
+
id = $result.vm.id.guid
|
162
|
+
}
|
163
|
+
|
164
|
+
$result = ConvertTo-Json $resultHash
|
165
|
+
Write-Output-Message $result
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
# get either cached or entered in the prompt credentials
|
3
|
+
function Get-Creds($server_address, $prompt_message, $username = $null, $password = $null )
|
4
|
+
{
|
5
|
+
$temp_folder = $env:temp
|
6
|
+
# get creds
|
7
|
+
$cred_file = $temp_folder + "\creds_$server_address.clixml"
|
8
|
+
if ( Test-Path $cred_file )
|
9
|
+
{
|
10
|
+
$credential = Import-CliXml $cred_file
|
11
|
+
} else
|
12
|
+
{
|
13
|
+
if ( $username -ne $null -and $password -ne $null )
|
14
|
+
{
|
15
|
+
# creds passed, use them
|
16
|
+
$password = ConvertTo-SecureString -string $password -asPlainText -force
|
17
|
+
$credential = New-Object System.Management.Automation.PSCredential($username, $password)
|
18
|
+
} else
|
19
|
+
{
|
20
|
+
$credential = Get-Credential -Message $prompt_message
|
21
|
+
}
|
22
|
+
$credential | Export-CliXml $cred_file
|
23
|
+
Write-host "Credentials for $server_address is cached in $cred_file"
|
24
|
+
}
|
25
|
+
return $credential
|
26
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
# add $address to trusted host list
|
3
|
+
function Add-To-Trusted($address)
|
4
|
+
{
|
5
|
+
$trusted_hosts = get-item wsman:\localhost\Client\TrustedHosts
|
6
|
+
if ( $address -as [ipaddress] -and !$trusted_hosts.Value.Contains($address) )
|
7
|
+
{
|
8
|
+
if ($trusted_hosts.Value)
|
9
|
+
{
|
10
|
+
$new_th_values = "$($trusted_hosts.Value),$address"
|
11
|
+
} else {
|
12
|
+
$new_th_values = $address
|
13
|
+
}
|
14
|
+
set-item wsman:\localhost\Client\TrustedHosts $new_th_values -Force
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
# remove $address from trusted host list
|
19
|
+
function Remove-From-Trusted($address)
|
20
|
+
{
|
21
|
+
# remove $address from trusted hosts
|
22
|
+
$trusted_hosts = get-item wsman:\localhost\Client\TrustedHosts
|
23
|
+
if ( $trusted_hosts.Value.Contains($address) )
|
24
|
+
{
|
25
|
+
$new_th_values = $trusted_hosts.Value -replace ",?$address", ""
|
26
|
+
set-item wsman:\localhost\Client\TrustedHosts $new_th_values -Force
|
27
|
+
}
|
28
|
+
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#
|
2
|
+
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
|
3
|
+
. ([System.IO.Path]::Combine($Dir, "manage_credentials.ps1"))
|
4
|
+
. ([System.IO.Path]::Combine($Dir, "manage_trusted_hosts.ps1"))
|
5
|
+
|
6
|
+
# execute script block for VMM
|
7
|
+
function execute($block, $vmm_server_address, $proxy_server_address)
|
8
|
+
{
|
9
|
+
$proxy_credential = $null
|
10
|
+
if ($proxy_server_address -ne $null )
|
11
|
+
{
|
12
|
+
$proxy_credential = Get-Creds $proxy_server_address "Credentials for proxy server: $proxy_server_address"
|
13
|
+
}
|
14
|
+
$vmm_credential = Get-Creds $vmm_server_address "Credentials for VMM server: $vmm_server_address"
|
15
|
+
|
16
|
+
#
|
17
|
+
$init_vmm_block = {
|
18
|
+
try {
|
19
|
+
ipmo 'C:\Program Files\Microsoft System Center 2012 R2\Virtual Machine Manager\bin\psModules\virtualmachinemanager'
|
20
|
+
} catch
|
21
|
+
{
|
22
|
+
write-error 'You need to install Virtual Machine Manager R2 client first.'
|
23
|
+
throw $_.Exception
|
24
|
+
}
|
25
|
+
#
|
26
|
+
$proxy_credential = $using:proxy_credential # make those available within $block as well
|
27
|
+
$vmm_server = Get-VMMServer -ComputerName $using:vmm_server_address -Credential $using:vmm_credential
|
28
|
+
}
|
29
|
+
# prepend init block to execution block
|
30
|
+
$block_to_run = [ScriptBlock]::Create($init_vmm_block.ToString() + $block.ToString())
|
31
|
+
#
|
32
|
+
if ( $proxy_server_address -eq $null )
|
33
|
+
{
|
34
|
+
$res = $(Start-Job $block_to_run | Wait-Job | Receive-Job)
|
35
|
+
} else
|
36
|
+
{
|
37
|
+
Add-To-Trusted $proxy_server_address
|
38
|
+
$so = New-PSSessionOption -IdleTimeout 240000
|
39
|
+
$res = invoke-command -ComputerName $proxy_server_address -Credential $proxy_credential -ScriptBlock $block_to_run -SessionOption $so
|
40
|
+
Remove-From-Trusted $proxy_server_address
|
41
|
+
}
|
42
|
+
return $res
|
43
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#-------------------------------------------------------------------------
|
2
|
+
# Copyright (c) Microsoft Open Technologies, Inc.
|
3
|
+
# All Rights Reserved. Licensed under the MIT License.
|
4
|
+
#--------------------------------------------------------------------------
|
5
|
+
|
6
|
+
function Write-Error-Message($message) {
|
7
|
+
$error_message = @{
|
8
|
+
error = "$message"
|
9
|
+
}
|
10
|
+
Write-Host "===Begin-Error==="
|
11
|
+
$result = ConvertTo-json $error_message
|
12
|
+
Write-Host $result
|
13
|
+
Write-Host "===End-Error==="
|
14
|
+
}
|
15
|
+
|
16
|
+
function Write-Output-Message($message) {
|
17
|
+
Write-Host "===Begin-Output==="
|
18
|
+
Write-Host $message
|
19
|
+
Write-Host "===End-Output==="
|
20
|
+
}
|
metadata
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kitchen-vmm
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jaroslav Gorjatsev
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-06-13 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: cane
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: finstyle
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: yard
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ! '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: test-kitchen
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.4'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ~>
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1.4'
|
125
|
+
description: Virtual Machine Manager Driver for Test-Kitchen
|
126
|
+
email:
|
127
|
+
- gjarik@gmail.com
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- .cane
|
133
|
+
- .gitignore
|
134
|
+
- .rubocop.yml
|
135
|
+
- .travis.yml
|
136
|
+
- CHANGELOG.md
|
137
|
+
- Gemfile
|
138
|
+
- LICENSE
|
139
|
+
- README.md
|
140
|
+
- Rakefile
|
141
|
+
- kitchen-vmm.gemspec
|
142
|
+
- lib/kitchen/driver/vmm.rb
|
143
|
+
- lib/kitchen/driver/vmm_utils.rb
|
144
|
+
- lib/kitchen/driver/vmm_version.rb
|
145
|
+
- support/delete_vm.ps1
|
146
|
+
- support/import_vm.ps1
|
147
|
+
- support/utils/manage_credentials.ps1
|
148
|
+
- support/utils/manage_trusted_hosts.ps1
|
149
|
+
- support/utils/vmm_executor.ps1
|
150
|
+
- support/utils/write_messages.ps1
|
151
|
+
homepage: https://github.com/jarig/kitchen-vmm
|
152
|
+
licenses:
|
153
|
+
- Apache 2
|
154
|
+
metadata: {}
|
155
|
+
post_install_message:
|
156
|
+
rdoc_options: []
|
157
|
+
require_paths:
|
158
|
+
- lib
|
159
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
161
|
+
- - ! '>='
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0'
|
164
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - ! '>='
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
requirements: []
|
170
|
+
rubyforge_project:
|
171
|
+
rubygems_version: 2.4.5
|
172
|
+
signing_key:
|
173
|
+
specification_version: 4
|
174
|
+
summary: Virtual Machine Manager Driver for Test-Kitchen
|
175
|
+
test_files: []
|