kitchen-qemu 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/kitchen/driver/qemu.rb +100 -27
- data/lib/kitchen/driver/qemu_version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a4524644c5f8decc92563913b719bed878cb8481
|
4
|
+
data.tar.gz: 48e60f381449ce1e9b9b123d7874d24b4d5b67c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 82fe2072030831acf5700f87178a8a889485dc949c8254540306dd9e290be1b657fd609688765ef85e548bfde5f1c9fb47a9df7cd26686035dac62639dccc244
|
7
|
+
data.tar.gz: 43b5e78b3dfb446405e0f2d809b33db8281fc44636851782c421d82321bbbbef755ea60149d0e4007e14c78ef4ea1c3293d3ddd961891a96622a7163a4251797
|
data/lib/kitchen/driver/qemu.rb
CHANGED
@@ -33,13 +33,14 @@ module Kitchen
|
|
33
33
|
kitchen_driver_api_version 2
|
34
34
|
plugin_version Kitchen::Driver::QEMU_VERSION
|
35
35
|
|
36
|
-
default_config :arch,
|
37
|
-
default_config :username,
|
38
|
-
default_config :password,
|
39
|
-
default_config :port,
|
40
|
-
default_config :display,
|
41
|
-
default_config :memory,
|
42
|
-
default_config :nic_model,
|
36
|
+
default_config :arch, 'x86_64'
|
37
|
+
default_config :username, 'kitchen'
|
38
|
+
default_config :password, 'kitchen'
|
39
|
+
default_config :port, 2222
|
40
|
+
default_config :display, 'none'
|
41
|
+
default_config :memory, '512'
|
42
|
+
default_config :nic_model, 'virtio'
|
43
|
+
default_config :hostshares, []
|
43
44
|
|
44
45
|
required_config :image do |_attr, value, _subject|
|
45
46
|
raise UserError, 'Must specify image file' unless value
|
@@ -60,6 +61,52 @@ module Kitchen
|
|
60
61
|
config[:binary] = @@ARCHBINARY[config[:arch]] or
|
61
62
|
raise UserError, "Unknown architecture '#{config[:arch]}'"
|
62
63
|
end
|
64
|
+
|
65
|
+
# kitchen-vagrant compatibility
|
66
|
+
config[:hostname] = config[:vm_hostname] if config[:hostname].nil?
|
67
|
+
|
68
|
+
acpi_poweroff = false
|
69
|
+
if config[:image].kind_of?(String)
|
70
|
+
config[:image] = [{
|
71
|
+
:file => config[:image],
|
72
|
+
:readonly => true,
|
73
|
+
:snapshot => true,
|
74
|
+
}]
|
75
|
+
else
|
76
|
+
raise UserError, "Invalid image entry for #{instance.to_str}" unless
|
77
|
+
config[:image].kind_of?(Array)
|
78
|
+
config[:image].each do |image|
|
79
|
+
raise UserError, "Invalid image entry for #{instance.to_str}" unless
|
80
|
+
image.kind_of?(Hash) && image[:file]
|
81
|
+
image[:snapshot] = true if image[:snapshot].nil?
|
82
|
+
image[:readonly] = image[:snapshot] if image[:readonly].nil?
|
83
|
+
acpi_poweroff = true unless image[:readonly]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
config[:acpi_poweroff] = acpi_poweroff if config[:acpi_poweroff].nil?
|
87
|
+
|
88
|
+
raise UserError, "Invalid share entry for #{instance.to_str}" unless
|
89
|
+
config[:hostshares].kind_of?(Array)
|
90
|
+
# kitchen-vagrant compatibility
|
91
|
+
if config[:hostshares].empty? && config[:synced_folders].kind_of?(Array)
|
92
|
+
config[:synced_folders].each do |folder|
|
93
|
+
if !folder[0].kind_of?(String) || !folder[1].kind_of?(String)
|
94
|
+
config[:hostshares].clear
|
95
|
+
break
|
96
|
+
end
|
97
|
+
config[:hostshares].push({ :path => folder[0], :mountpoint => folder[1] })
|
98
|
+
end
|
99
|
+
else
|
100
|
+
config[:hostshares].each do |share|
|
101
|
+
raise UserError, "Invalid share entry for #{instance.to_str}" unless
|
102
|
+
share.kind_of?(Hash) && share[:path]
|
103
|
+
raise UserError, "No mountpoint defined for share '#{share[:path]}' of #{instance.to_str}" unless
|
104
|
+
share[:mountpoint]
|
105
|
+
raise UserError, "Invalid mount options for share '#{share[:path]}' of #{instance.to_str}" unless
|
106
|
+
share[:mount_options].nil? || share[:mount_options].kind_of?(Array)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
63
110
|
config[:vga] = 'qxl' if config[:spice] && !config[:vga]
|
64
111
|
self
|
65
112
|
end
|
@@ -69,7 +116,7 @@ module Kitchen
|
|
69
116
|
# @param state [Hash] mutable instance and driver state
|
70
117
|
# @raise [ActionFailed] if the action could not be completed
|
71
118
|
def create(state)
|
72
|
-
monitor =
|
119
|
+
monitor = monitor_path
|
73
120
|
if File.exist?(monitor)
|
74
121
|
begin
|
75
122
|
mon = UNIXSocket.new(monitor)
|
@@ -84,28 +131,24 @@ module Kitchen
|
|
84
131
|
|
85
132
|
create_privkey or raise ActionFailed, "Unable to create file '#{privkey_path}'"
|
86
133
|
|
87
|
-
fqdn = config[:
|
134
|
+
fqdn = config[:hostname] || instance.name
|
88
135
|
hostname = fqdn.match(/^([^.]+)/)[0]
|
89
136
|
|
90
|
-
state[:hostname]
|
91
|
-
state[:port]
|
92
|
-
state[:username]
|
93
|
-
state[:password]
|
137
|
+
state[:hostname] = 'localhost'
|
138
|
+
state[:port] = config[:port]
|
139
|
+
state[:username] = config[:username]
|
140
|
+
state[:password] = config[:password]
|
141
|
+
state[:acpi_poweroff] = config[:acpi_poweroff]
|
94
142
|
|
95
143
|
cmd = [
|
96
144
|
config[:binary], '-daemonize',
|
97
145
|
'-display', config[:display].to_s,
|
98
146
|
'-chardev', "socket,id=mon-qmp,path=#{monitor},server,nowait",
|
99
147
|
'-mon', 'chardev=mon-qmp,mode=control,default',
|
100
|
-
'-
|
101
|
-
'-mon', 'chardev=mon-rdl,mode=readline',
|
148
|
+
'-serial', "mon:unix:path=#{serial_path},server,nowait",
|
102
149
|
'-m', config[:memory].to_s,
|
103
150
|
'-net', "nic,model=#{config[:nic_model]}",
|
104
151
|
'-net', "user,net=192.168.1.0/24,hostname=#{hostname},hostfwd=tcp::#{state[:port]}-:22",
|
105
|
-
'-device', 'virtio-scsi-pci,id=scsi',
|
106
|
-
'-device', 'scsi-hd,drive=root',
|
107
|
-
'-drive', "if=none,id=root,readonly,file=#{config[:image]}",
|
108
|
-
'-snapshot',
|
109
152
|
]
|
110
153
|
|
111
154
|
kvm = config[:kvm]
|
@@ -131,6 +174,25 @@ module Kitchen
|
|
131
174
|
cmd.push('-spice', config[:spice].to_s) if config[:spice]
|
132
175
|
cmd.push('-vnc', config[:vnc].to_s) if config[:vnc]
|
133
176
|
|
177
|
+
cmd.push('-device', 'virtio-scsi-pci,id=scsi')
|
178
|
+
config[:image].each_with_index do |image, i|
|
179
|
+
drive = ['if=none', "id=drive#{i}"]
|
180
|
+
drive.push('readonly') if image[:readonly]
|
181
|
+
drive.push('snapshot=on') if image[:snapshot]
|
182
|
+
drive.push("file=#{image[:file]}")
|
183
|
+
cmd.push('-device', "scsi-hd,drive=drive#{i}",
|
184
|
+
'-drive', drive.join(','))
|
185
|
+
end
|
186
|
+
|
187
|
+
config[:hostshares].each_with_index do |share, i|
|
188
|
+
path = share[:path]
|
189
|
+
path = "#{config[:kitchen_root]}/#{path}" unless path[0] == '/'
|
190
|
+
raise ActionFailed, "Share path '#{path}' not a directory" unless
|
191
|
+
::File.directory?(path)
|
192
|
+
cmd.push('-fsdev', "local,id=fsdev#{i},security_model=none,path=#{path}",
|
193
|
+
'-device', "virtio-9p-pci,fsdev=fsdev#{i},mount_tag=path#{i}")
|
194
|
+
end
|
195
|
+
|
134
196
|
info 'Spawning QEMU..'
|
135
197
|
error = nil
|
136
198
|
Open3.popen3({ 'QEMU_AUDIO_DRV' => 'none' }, *cmd) do |_, _, err, thr|
|
@@ -155,6 +217,11 @@ module Kitchen
|
|
155
217
|
conn.execute("sudo sh -c 'echo 127.0.0.1 #{names} >> /etc/hosts; hostnamectl set-hostname #{hostname} || hostname #{hostname} || true' 2>/dev/null")
|
156
218
|
conn.execute('install -dm700 "$HOME/.ssh"')
|
157
219
|
conn.execute("echo '#{@@PUBKEY}' > \"$HOME/.ssh/authorized_keys\"")
|
220
|
+
config[:hostshares].each_with_index do |share, i|
|
221
|
+
options = share[:mount_options] ?
|
222
|
+
share[:mount_options].join(',') : 'cache=none,access=any,version=9p2000.L'
|
223
|
+
conn.execute("sudo sh -c 'install -dm755 \"#{share[:mountpoint]}\" && mount -t 9p -o trans=virtio,#{options} path#{i} \"#{share[:mountpoint]}\"'")
|
224
|
+
end
|
158
225
|
conn.close
|
159
226
|
state[:ssh_key] = privkey_path
|
160
227
|
end
|
@@ -164,16 +231,22 @@ module Kitchen
|
|
164
231
|
# @param state [Hash] mutable instance state
|
165
232
|
# @raise [ActionFailed] if the action could not be completed
|
166
233
|
def destroy(state)
|
167
|
-
monitor =
|
234
|
+
monitor = monitor_path
|
168
235
|
return unless File.exist?(monitor)
|
169
236
|
|
170
237
|
instance.transport.connection(state).close
|
171
238
|
|
172
239
|
begin
|
173
240
|
mon = QMPClient.new(UNIXSocket.new(monitor), 2)
|
174
|
-
|
175
|
-
|
176
|
-
|
241
|
+
if state[:acpi_poweroff]
|
242
|
+
info 'Sending ACPI poweroff..'
|
243
|
+
mon.execute('system_powerdown')
|
244
|
+
mon.wait_for_eof(30)
|
245
|
+
else
|
246
|
+
info 'Quitting QEMU..'
|
247
|
+
mon.execute('quit')
|
248
|
+
mon.wait_for_eof(5)
|
249
|
+
end
|
177
250
|
mon.close
|
178
251
|
rescue Errno::ECONNREFUSED
|
179
252
|
info 'Connection to monitor refused. Assuming QEMU already quit.'
|
@@ -231,11 +304,11 @@ tY4IM9IaSC2LuPFVc0Kx6TwObdeQScOokIxL3HfayfLKieTLC+w2
|
|
231
304
|
File.join(config[:kitchen_root], '.kitchen', 'kitchen-qemu.key')
|
232
305
|
end
|
233
306
|
|
234
|
-
def
|
307
|
+
def monitor_path
|
235
308
|
File.join(config[:kitchen_root], '.kitchen', "#{instance.name}.qmp")
|
236
309
|
end
|
237
310
|
|
238
|
-
def
|
311
|
+
def serial_path
|
239
312
|
File.join(config[:kitchen_root], '.kitchen', "#{instance.name}.mon")
|
240
313
|
end
|
241
314
|
|
@@ -247,12 +320,12 @@ tY4IM9IaSC2LuPFVc0Kx6TwObdeQScOokIxL3HfayfLKieTLC+w2
|
|
247
320
|
|
248
321
|
def cleanup!
|
249
322
|
begin
|
250
|
-
File.delete(
|
323
|
+
File.delete(monitor_path)
|
251
324
|
rescue Errno::ENOENT
|
252
325
|
# do nothing
|
253
326
|
end
|
254
327
|
begin
|
255
|
-
File.delete(
|
328
|
+
File.delete(serial_path)
|
256
329
|
rescue Errno::ENOENT
|
257
330
|
# do nothing
|
258
331
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kitchen-qemu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Emil Renner Berthing
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: test-kitchen
|