libvirt_ffi 0.6.1 → 0.8.1
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/.github/workflows/tests.yml +26 -0
- data/.gitignore +2 -1
- data/.rspec +1 -0
- data/.rubocop.yml +1 -1
- data/Gemfile +7 -10
- data/README.md +2 -2
- data/Rakefile +3 -8
- data/lib/libvirt/base_info.rb +8 -0
- data/lib/libvirt/connection.rb +228 -69
- data/lib/libvirt/domain.rb +18 -0
- data/lib/libvirt/ffi/domain.rb +53 -41
- data/lib/libvirt/ffi/host.rb +78 -39
- data/lib/libvirt/ffi/interface.rb +175 -0
- data/lib/libvirt/ffi/network.rb +392 -0
- data/lib/libvirt/ffi/storage.rb +1 -1
- data/lib/libvirt/ffi.rb +2 -0
- data/lib/libvirt/host_callback_storage.rb +10 -2
- data/lib/libvirt/interface.rb +92 -0
- data/lib/libvirt/loggable.rb +58 -0
- data/lib/libvirt/network.rb +176 -0
- data/lib/libvirt/network_dhcp_lease.rb +20 -0
- data/lib/libvirt/storage_pool.rb +2 -2
- data/lib/libvirt/util.rb +87 -64
- data/lib/libvirt/version.rb +1 -1
- data/lib/libvirt/xml/generic.rb +8 -5
- data/lib/libvirt/xml/interface.rb +79 -0
- data/lib/libvirt/xml/ip_address.rb +51 -0
- data/lib/libvirt/xml/network.rb +204 -0
- data/lib/libvirt/xml.rb +6 -2
- data/lib/libvirt.rb +18 -16
- data/libvirt.gemspec +11 -13
- metadata +14 -26
- data/.travis.yml +0 -6
- data/test_usage/support/libvirt_async.rb +0 -536
- data/test_usage/support/log_formatter.rb +0 -33
- data/test_usage/test_domain.rb +0 -43
- data/test_usage/test_event_loop.rb +0 -185
- data/test_usage/test_libvirtd_restart.rb +0 -63
- data/test_usage/test_metadata.rb +0 -104
- data/test_usage/test_screenshot.rb +0 -197
- data/test_usage/test_storage.rb +0 -52
@@ -1,536 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module LibvirtAsync
|
4
|
-
class << self
|
5
|
-
attr_writer :logger
|
6
|
-
|
7
|
-
attr_reader :logger
|
8
|
-
end
|
9
|
-
|
10
|
-
module WithDbg
|
11
|
-
extend ActiveSupport::Concern
|
12
|
-
|
13
|
-
class_methods do
|
14
|
-
def dbg(progname = nil, &block)
|
15
|
-
LibvirtAsync.logger&.debug(progname || "#{name}.:0x#{object_id.to_s(16)}", &block)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def dbg(progname = nil, &block)
|
22
|
-
LibvirtAsync.logger&.debug(progname || "#{self.class}#:0x#{object_id.to_s(16)}", &block)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
module Util
|
27
|
-
def self.create_task(parent = nil, reactor = nil, &block)
|
28
|
-
parent = Async::Task.current? if parent == :current
|
29
|
-
reactor ||= Async::Task.current.reactor
|
30
|
-
Async::Task.new(reactor, parent, &block)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
class Handle
|
35
|
-
# Represents an event handle (usually a file descriptor). When an event
|
36
|
-
# happens to the handle, we dispatch the event to libvirt via
|
37
|
-
# Libvirt::event_invoke_handle_callback (feeding it the handle_id we returned
|
38
|
-
# from add_handle, the file descriptor, the new events, and the opaque
|
39
|
-
# data that libvirt gave us earlier).
|
40
|
-
|
41
|
-
class Monitor < Async::Wrapper
|
42
|
-
def close
|
43
|
-
cancel_monitor
|
44
|
-
end
|
45
|
-
|
46
|
-
def readiness
|
47
|
-
monitor&.readiness
|
48
|
-
end
|
49
|
-
|
50
|
-
def to_s
|
51
|
-
"#<#{self.class}:0x#{object_id.to_s(16)} readable=#{@readable&.object_id&.to_s(16)} writable=#{@writable&.object_id&.to_s(16)} alive=#{@monitor && !@monitor.closed?}>"
|
52
|
-
end
|
53
|
-
|
54
|
-
def inspect
|
55
|
-
to_s
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
include WithDbg
|
60
|
-
|
61
|
-
attr_reader :handle_id, :fd, :opaque, :monitor
|
62
|
-
attr_accessor :events
|
63
|
-
|
64
|
-
def initialize(handle_id, fd, events, opaque)
|
65
|
-
dbg { "#{self.class}#initialize handle_id=#{handle_id}, fd=#{fd}, events=#{events}" }
|
66
|
-
|
67
|
-
@handle_id = handle_id
|
68
|
-
@fd = fd
|
69
|
-
@events = events
|
70
|
-
@opaque = opaque
|
71
|
-
@monitor = nil
|
72
|
-
end
|
73
|
-
|
74
|
-
def register
|
75
|
-
dbg { "#{self.class}#register handle_id=#{handle_id}, fd=#{fd}" }
|
76
|
-
|
77
|
-
dbg { "#{self.class}#register skip EVENT_HANDLE_ERROR handle_id=#{handle_id}, fd=#{fd}" } if (events & Libvirt::EVENT_HANDLE_ERROR) != 0
|
78
|
-
dbg { "#{self.class}#register skip EVENT_HANDLE_HANGUP handle_id=#{handle_id}, fd=#{fd}" } if (events & Libvirt::EVENT_HANDLE_HANGUP) != 0
|
79
|
-
|
80
|
-
interest = events_to_interest(events)
|
81
|
-
dbg { "#{self.class}#register parse handle_id=#{handle_id}, fd=#{fd}, events=#{events}, interest=#{interest}" }
|
82
|
-
|
83
|
-
if interest.nil?
|
84
|
-
dbg { "#{self.class}#register no interest handle_id=#{handle_id}, fd=#{fd}" }
|
85
|
-
return
|
86
|
-
end
|
87
|
-
|
88
|
-
task = Util.create_task do
|
89
|
-
dbg { "#{self.class}#register_handle Async start handle_id=#{handle_id}, fd=#{fd}" }
|
90
|
-
io_mode = interest_to_io_mode(interest)
|
91
|
-
|
92
|
-
io = IO.new(fd, io_mode, autoclose: false)
|
93
|
-
@monitor = Monitor.new(io)
|
94
|
-
|
95
|
-
while @monitor.readiness.nil?
|
96
|
-
cancelled = wait_io(interest)
|
97
|
-
|
98
|
-
if cancelled
|
99
|
-
dbg { "#{self.class}#register_handle async cancel handle_id=#{handle_id}, fd=#{fd}" }
|
100
|
-
break
|
101
|
-
end
|
102
|
-
|
103
|
-
dbg { "#{self.class}#register_handle async resumes readiness=#{@monitor.readiness}, handle_id=#{handle_id}, fd=#{fd}" }
|
104
|
-
events = readiness_to_events(@monitor.readiness)
|
105
|
-
|
106
|
-
unless events.nil?
|
107
|
-
dispatch(events)
|
108
|
-
break
|
109
|
-
end
|
110
|
-
|
111
|
-
dbg { "#{self.class}#register_handle async not ready readiness=#{@monitor.readiness}, handle_id=#{handle_id}, fd=#{fd}" }
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
dbg { "#{self.class}#register_handle invokes fiber=0x#{task.fiber.object_id.to_s(16)} handle_id=#{handle_id}, fd=#{fd}" }
|
116
|
-
task.run
|
117
|
-
dbg { "#{self.class}#register_handle ends handle_id=#{handle_id}, fd=#{fd}" }
|
118
|
-
end
|
119
|
-
|
120
|
-
def unregister
|
121
|
-
dbg { "#{self.class}#unregister handle_id=#{handle_id}, fd=#{fd}" }
|
122
|
-
|
123
|
-
if @monitor.nil?
|
124
|
-
dbg { "#{self.class}#unregister already unregistered handle_id=#{handle_id}, fd=#{fd}" }
|
125
|
-
return
|
126
|
-
end
|
127
|
-
|
128
|
-
@monitor.close
|
129
|
-
@monitor = nil
|
130
|
-
end
|
131
|
-
|
132
|
-
def to_s
|
133
|
-
"#<#{self.class}:0x#{object_id.to_s(16)} handle_id=#{handle_id} fd=#{fd} events=#{events} monitor=#{monitor}>"
|
134
|
-
end
|
135
|
-
|
136
|
-
def inspect
|
137
|
-
to_s
|
138
|
-
end
|
139
|
-
|
140
|
-
private
|
141
|
-
|
142
|
-
def dispatch(events)
|
143
|
-
dbg { "#{self.class}#dispatch starts handle_id=#{handle_id}, events=#{events}, fd=#{fd}" }
|
144
|
-
|
145
|
-
task = Util.create_task do
|
146
|
-
dbg { "#{self.class}#dispatch async starts handle_id=#{handle_id} events=#{events}, fd=#{fd}" }
|
147
|
-
# Libvirt::event_invoke_handle_callback(handle_id, fd, events, opaque)
|
148
|
-
# opaque.call_cb(handle_id, fd, events)
|
149
|
-
Libvirt::Event.invoke_handle_callback(handle_id, fd, events, opaque)
|
150
|
-
dbg { "#{self.class}#dispatch async ends handle_id=#{handle_id} received_events=#{events}, fd=#{fd}" }
|
151
|
-
end
|
152
|
-
# dbg { "#{self.class}#dispatch invokes fiber=0x#{task.fiber.object_id.to_s(16)} handle_id=#{handle_id}, events=#{events}, fd=#{fd}" }
|
153
|
-
# task.run
|
154
|
-
# dbg { "#{self.class}#dispatch ends handle_id=#{handle_id}, events=#{events}, fd=#{fd}" }
|
155
|
-
dbg { "#{self.class}#dispatch schedules fiber=0x#{task.fiber.object_id.to_s(16)} handle_id=#{handle_id}, events=#{events}, fd=#{fd}" }
|
156
|
-
task.reactor << task.fiber
|
157
|
-
end
|
158
|
-
|
159
|
-
def wait_io(interest)
|
160
|
-
meth = interest_to_monitor_method(interest)
|
161
|
-
begin
|
162
|
-
@monitor.public_send(meth)
|
163
|
-
false
|
164
|
-
rescue Monitor::Cancelled => e
|
165
|
-
dbg { "#{self.class}#wait_io cancelled #{e.class} #{e.message}" }
|
166
|
-
true
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
def interest_to_monitor_method(interest)
|
171
|
-
case interest
|
172
|
-
when :r
|
173
|
-
:wait_readable
|
174
|
-
when :w
|
175
|
-
:wait_writable
|
176
|
-
when :rw
|
177
|
-
:wait_any
|
178
|
-
else
|
179
|
-
raise ArgumentError, "invalid interest #{interest}"
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
def events_to_interest(events)
|
184
|
-
readable = (events & Libvirt::EVENT_HANDLE_READABLE) != 0
|
185
|
-
writable = (events & Libvirt::EVENT_HANDLE_WRITABLE) != 0
|
186
|
-
if readable && writable
|
187
|
-
:rw
|
188
|
-
elsif readable
|
189
|
-
:r
|
190
|
-
elsif writable
|
191
|
-
:w
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
def interest_to_io_mode(interest)
|
196
|
-
case interest
|
197
|
-
when :rw
|
198
|
-
'a+'
|
199
|
-
when :r
|
200
|
-
'r'
|
201
|
-
when :w
|
202
|
-
'w'
|
203
|
-
else
|
204
|
-
raise ArgumentError, "invalid interest #{interest}"
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
def readiness_to_events(readiness)
|
209
|
-
case readiness&.to_sym
|
210
|
-
when :rw
|
211
|
-
Libvirt::EVENT_HANDLE_READABLE | Libvirt::EVENT_HANDLE_WRITABLE
|
212
|
-
when :r
|
213
|
-
Libvirt::EVENT_HANDLE_READABLE
|
214
|
-
when :w
|
215
|
-
Libvirt::EVENT_HANDLE_WRITABLE
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
class Timer
|
221
|
-
# Represents a When a timer expires, we dispatch the event to
|
222
|
-
# libvirt via Libvirt::event_invoke_timeout_callback (feeding it the timer_id
|
223
|
-
# we returned from add_timer and the opaque data that libvirt gave us
|
224
|
-
# earlier).
|
225
|
-
|
226
|
-
class Monitor
|
227
|
-
class Cancelled < StandardError
|
228
|
-
def initialize
|
229
|
-
super('was cancelled')
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
attr_reader :fiber
|
234
|
-
|
235
|
-
def initialize
|
236
|
-
@fiber = nil
|
237
|
-
end
|
238
|
-
|
239
|
-
def wait(timeout)
|
240
|
-
@fiber = Async::Task.current.fiber
|
241
|
-
Async::Task.current.sleep(timeout)
|
242
|
-
@fiber = nil
|
243
|
-
end
|
244
|
-
|
245
|
-
def close
|
246
|
-
@fiber.resume(Cancelled.new) if @fiber&.alive?
|
247
|
-
@fiber = nil
|
248
|
-
end
|
249
|
-
|
250
|
-
def to_s
|
251
|
-
"#<#{self.class}:0x#{object_id.to_s(16)} fiber=#{@fiber&.object_id&.to_s(16)} alive=#{@fiber&.alive?}>"
|
252
|
-
end
|
253
|
-
|
254
|
-
def inspect
|
255
|
-
to_s
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
include WithDbg
|
260
|
-
|
261
|
-
attr_reader :timer_id, :opaque, :monitor
|
262
|
-
attr_accessor :last_fired, :interval
|
263
|
-
|
264
|
-
def initialize(timer_id, interval, opaque)
|
265
|
-
dbg { "#{self.class}#initialize timer_id=#{timer_id}, interval=#{interval}" }
|
266
|
-
|
267
|
-
@timer_id = timer_id
|
268
|
-
@interval = interval / 1000.0
|
269
|
-
@opaque = opaque
|
270
|
-
@last_fired = Time.now.to_f
|
271
|
-
@monitor = nil
|
272
|
-
end
|
273
|
-
|
274
|
-
def wait_time
|
275
|
-
return if interval.negative?
|
276
|
-
|
277
|
-
last_fired + interval
|
278
|
-
end
|
279
|
-
|
280
|
-
def register
|
281
|
-
dbg { "#{self.class}#register starts timer_id=#{timer_id}, interval=#{interval}" }
|
282
|
-
|
283
|
-
if wait_time.nil?
|
284
|
-
dbg { "#{self.class}#register no wait time timer_id=#{timer_id}, interval=#{interval}" }
|
285
|
-
return
|
286
|
-
end
|
287
|
-
|
288
|
-
task = Util.create_task do
|
289
|
-
dbg { "#{self.class}#register async starts timer_id=#{timer_id}, interval=#{interval}" }
|
290
|
-
now_time = Time.now.to_f
|
291
|
-
timeout = wait_time > now_time ? wait_time - now_time : 0
|
292
|
-
@monitor = Monitor.new
|
293
|
-
cancelled = wait_timer(timeout)
|
294
|
-
|
295
|
-
if cancelled
|
296
|
-
dbg { "#{self.class}#register async cancel timer_id=#{timer_id}, interval=#{interval}" }
|
297
|
-
else
|
298
|
-
dbg { "#{self.class}#register async ready timer_id=#{timer_id}, interval=#{interval}" }
|
299
|
-
self.last_fired = Time.now.to_f
|
300
|
-
dispatch
|
301
|
-
end
|
302
|
-
end
|
303
|
-
|
304
|
-
dbg { "#{self.class}#register invokes fiber=0x#{task.fiber.object_id.to_s(16)} timer_id=#{timer_id}, interval=#{interval}" }
|
305
|
-
task.run
|
306
|
-
dbg { "#{self.class}#register ends timer_id=#{timer_id}, interval=#{interval}" }
|
307
|
-
end
|
308
|
-
|
309
|
-
def unregister
|
310
|
-
dbg { "#{self.class}#unregister_timer timer_id=#{timer_id}, interval=#{interval}" }
|
311
|
-
|
312
|
-
if @monitor.nil?
|
313
|
-
dbg { "#{self.class}#unregister_timer already unregistered timer_id=#{timer_id}, interval=#{interval}" }
|
314
|
-
return
|
315
|
-
end
|
316
|
-
|
317
|
-
@monitor.close
|
318
|
-
@monitor = nil
|
319
|
-
end
|
320
|
-
|
321
|
-
def to_s
|
322
|
-
"#<#{self.class}:0x#{object_id.to_s(16)} timer_id=#{timer_id} interval=#{interval} last_fired=#{last_fired} monitor=#{monitor}>"
|
323
|
-
end
|
324
|
-
|
325
|
-
def inspect
|
326
|
-
to_s
|
327
|
-
end
|
328
|
-
|
329
|
-
private
|
330
|
-
|
331
|
-
def dispatch
|
332
|
-
dbg { "#{self.class}#dispatch starts timer_id=#{timer_id}, interval=#{interval}" }
|
333
|
-
|
334
|
-
task = Util.create_task do
|
335
|
-
dbg { "#{self.class}#dispatch async starts timer_id=#{timer_id}, interval=#{interval}" }
|
336
|
-
# Libvirt::event_invoke_timeout_callback(timer_id, opaque)
|
337
|
-
# opaque.call_cb(timer_id)
|
338
|
-
Libvirt::Event.invoke_timeout_callback(timer_id, opaque)
|
339
|
-
dbg { "#{self.class}#dispatch async async ends timer_id=#{timer_id}, interval=#{interval}" }
|
340
|
-
end
|
341
|
-
|
342
|
-
# dbg { "#{self.class}#dispatch invokes fiber=0x#{task.fiber.object_id.to_s(16)} timer_id=#{timer_id}, interval=#{interval}" }
|
343
|
-
# task.run
|
344
|
-
# dbg { "#{self.class}#dispatch ends timer_id=#{timer_id}, interval=#{interval}" }
|
345
|
-
dbg { "#{self.class}#dispatch schedules fiber=0x#{task.fiber.object_id.to_s(16)} timer_id=#{timer_id}, interval=#{interval}" }
|
346
|
-
task.reactor << task.fiber
|
347
|
-
end
|
348
|
-
|
349
|
-
def wait_timer(timeout)
|
350
|
-
@monitor.wait(timeout)
|
351
|
-
false
|
352
|
-
rescue Monitor::Cancelled => e
|
353
|
-
dbg { "#{self.class}#wait_timer cancelled #{e.class} #{e.message}" }
|
354
|
-
true
|
355
|
-
end
|
356
|
-
end
|
357
|
-
|
358
|
-
class Implementations
|
359
|
-
include WithDbg
|
360
|
-
|
361
|
-
def initialize
|
362
|
-
dbg { "#{self.class}#initialize" }
|
363
|
-
|
364
|
-
default_variables
|
365
|
-
end
|
366
|
-
|
367
|
-
def start
|
368
|
-
dbg { "#{self.class}#start" }
|
369
|
-
|
370
|
-
register_implementations
|
371
|
-
end
|
372
|
-
|
373
|
-
def stop
|
374
|
-
dbg { "#{self.class}#stop" }
|
375
|
-
|
376
|
-
@handles.each(&:unregister)
|
377
|
-
@timers.each(&:unregister)
|
378
|
-
|
379
|
-
default_variables
|
380
|
-
end
|
381
|
-
|
382
|
-
def print_debug_info
|
383
|
-
str = [
|
384
|
-
"#{self.class}:0x#{object_id.to_s(16)}",
|
385
|
-
'handles = [',
|
386
|
-
@handles.map(&:to_s).join("\n"),
|
387
|
-
']',
|
388
|
-
'timers = [',
|
389
|
-
@timers.map(&:to_s).join("\n"),
|
390
|
-
']'
|
391
|
-
].join("\n")
|
392
|
-
Libvirt.logger&.debug { str }
|
393
|
-
end
|
394
|
-
|
395
|
-
def to_s
|
396
|
-
"#<#{self.class}:0x#{object_id.to_s(16)} handles=#{@handles} timers=#{@timers}>"
|
397
|
-
end
|
398
|
-
|
399
|
-
def inspect
|
400
|
-
to_s
|
401
|
-
end
|
402
|
-
|
403
|
-
private
|
404
|
-
|
405
|
-
def default_variables
|
406
|
-
@next_handle_id = 1
|
407
|
-
@next_timer_id = 1
|
408
|
-
@handles = []
|
409
|
-
@timers = []
|
410
|
-
end
|
411
|
-
|
412
|
-
def register_implementations
|
413
|
-
dbg { "#{self.class}#register_implementations" }
|
414
|
-
|
415
|
-
Libvirt::Event.register(
|
416
|
-
add_handle: method(:add_handle).to_proc,
|
417
|
-
update_handle: method(:update_handle).to_proc,
|
418
|
-
remove_handle: method(:remove_handle).to_proc,
|
419
|
-
add_timer: method(:add_timer).to_proc,
|
420
|
-
update_timer: method(:update_timer).to_proc,
|
421
|
-
remove_timer: method(:remove_timer).to_proc,
|
422
|
-
schedule: method(:schedule).to_proc
|
423
|
-
)
|
424
|
-
end
|
425
|
-
|
426
|
-
def schedule(&block)
|
427
|
-
task = Async::Task.new(Async::Task.current.reactor, nil, &block)
|
428
|
-
task.reactor << task.fiber
|
429
|
-
end
|
430
|
-
|
431
|
-
def add_handle(fd, events, opaque)
|
432
|
-
# add a handle to be tracked by this object. The application is
|
433
|
-
# expected to maintain a list of internal handle IDs (integers); this
|
434
|
-
# callback *must* return the current handle_id. This handle_id is used
|
435
|
-
# both by libvirt to identify the handle (during an update or remove
|
436
|
-
# callback), and is also passed by the application into libvirt when
|
437
|
-
# dispatching an event. The application *must* also store the opaque
|
438
|
-
# data given by libvirt, and return it back to libvirt later
|
439
|
-
# (see remove_handle)
|
440
|
-
dbg { "#{self.class}#add_handle starts fd=#{fd}, events=#{events}" }
|
441
|
-
|
442
|
-
@next_handle_id += 1
|
443
|
-
handle_id = @next_handle_id
|
444
|
-
handle = LibvirtAsync::Handle.new(handle_id, fd, events, opaque)
|
445
|
-
@handles << handle
|
446
|
-
handle.register
|
447
|
-
|
448
|
-
dbg { "#{self.class}#add_handle ends fd=#{fd}, events=#{events}" }
|
449
|
-
handle_id
|
450
|
-
end
|
451
|
-
|
452
|
-
def update_handle(handle_id, events)
|
453
|
-
# update a previously registered handle. Libvirt tells us the handle_id
|
454
|
-
# (which was returned to libvirt via add_handle), and the new events. It
|
455
|
-
# is our responsibility to find the correct handle and update the events
|
456
|
-
# it cares about
|
457
|
-
dbg { "#{self.class}#update_handle starts handle_id=#{handle_id}, events=#{events}" }
|
458
|
-
|
459
|
-
handle = @handles.detect { |h| h.handle_id == handle_id }
|
460
|
-
handle.events = events
|
461
|
-
handle.unregister
|
462
|
-
handle.register
|
463
|
-
|
464
|
-
dbg { "#{self.class}#update_handle ends handle_id=#{handle_id}, events=#{events}" }
|
465
|
-
nil
|
466
|
-
end
|
467
|
-
|
468
|
-
def remove_handle(handle_id)
|
469
|
-
# remove a previously registered handle. Libvirt tells us the handle_id
|
470
|
-
# (which was returned to libvirt via add_handle), and it is our
|
471
|
-
# responsibility to "forget" the handle. We must return the opaque data
|
472
|
-
# that libvirt handed us in "add_handle", otherwise we will leak memory
|
473
|
-
dbg { "#{self.class}#remove_handle starts handle_id=#{handle_id}" }
|
474
|
-
|
475
|
-
idx = @handles.index { |h| h.handle_id == handle_id }
|
476
|
-
handle = @handles.delete_at(idx)
|
477
|
-
handle.unregister
|
478
|
-
|
479
|
-
dbg { "#{self.class}#remove_handle starts handle_id=#{handle_id}" }
|
480
|
-
handle.opaque
|
481
|
-
end
|
482
|
-
|
483
|
-
def add_timer(interval, opaque)
|
484
|
-
# add a timeout to be tracked by this object. The application is
|
485
|
-
# expected to maintain a list of internal timer IDs (integers); this
|
486
|
-
# callback *must* return the current timer_id. This timer_id is used
|
487
|
-
# both by libvirt to identify the timeout (during an update or remove
|
488
|
-
# callback), and is also passed by the application into libvirt when
|
489
|
-
# dispatching an event. The application *must* also store the opaque
|
490
|
-
# data given by libvirt, and return it back to libvirt later
|
491
|
-
# (see remove_timer)
|
492
|
-
dbg { "#{self.class}#add_timer starts interval=#{interval}" }
|
493
|
-
|
494
|
-
@next_timer_id += 1
|
495
|
-
timer_id = @next_timer_id
|
496
|
-
timer = LibvirtAsync::Timer.new(timer_id, interval, opaque)
|
497
|
-
@timers << timer
|
498
|
-
timer.register
|
499
|
-
|
500
|
-
dbg { "#{self.class}#add_timer ends interval=#{interval}" }
|
501
|
-
timer_id
|
502
|
-
end
|
503
|
-
|
504
|
-
def update_timer(timer_id, interval)
|
505
|
-
# update a previously registered timer. Libvirt tells us the timer_id
|
506
|
-
# (which was returned to libvirt via add_timer), and the new interval. It
|
507
|
-
# is our responsibility to find the correct timer and update the timers
|
508
|
-
# it cares about
|
509
|
-
dbg { "#{self.class}#update_timer starts timer_id=#{timer_id}, interval=#{interval}" }
|
510
|
-
|
511
|
-
timer = @timers.detect { |t| t.timer_id == timer_id }
|
512
|
-
dbg { "#{self.class}#update_timer updating timer_id=#{timer.timer_id}" }
|
513
|
-
timer.interval = interval
|
514
|
-
timer.unregister
|
515
|
-
timer.register
|
516
|
-
|
517
|
-
dbg { "#{self.class}#update_timer ends timer_id=#{timer_id}, interval=#{interval}" }
|
518
|
-
nil
|
519
|
-
end
|
520
|
-
|
521
|
-
def remove_timer(timer_id)
|
522
|
-
# remove a previously registered timeout. Libvirt tells us the timer_id
|
523
|
-
# (which was returned to libvirt via add_timer), and it is our
|
524
|
-
# responsibility to "forget" the timer. We must return the opaque data
|
525
|
-
# that libvirt handed us in "add_timer", otherwise we will leak memory
|
526
|
-
dbg { "#{self.class}#remove_timer starts timer_id=#{timer_id}" }
|
527
|
-
|
528
|
-
idx = @timers.index { |t| t.timer_id == timer_id }
|
529
|
-
timer = @timers.delete_at(idx)
|
530
|
-
timer.unregister
|
531
|
-
|
532
|
-
dbg { "#{self.class}#remove_timer ends timer_id=#{timer_id}" }
|
533
|
-
timer.opaque
|
534
|
-
end
|
535
|
-
end
|
536
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class LogFormatter
|
4
|
-
LOG_FORMAT = "%s, %s [%s/%s/%s] %s\n"
|
5
|
-
DEFAULT_DATETIME_FORMAT = '%F %T.%N'
|
6
|
-
|
7
|
-
attr_accessor :datetime_format
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
@datetime_format = nil
|
11
|
-
end
|
12
|
-
|
13
|
-
def call(severity, time, progname, message)
|
14
|
-
format(LOG_FORMAT, severity[0..0], format_datetime(time), "0x#{Async::Task.current?&.object_id&.to_s(16)}", "0x#{Fiber.current.object_id.to_s(16)}", progname, format_message(message))
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def format_datetime(time)
|
20
|
-
time.strftime(@datetime_format || DEFAULT_DATETIME_FORMAT)
|
21
|
-
end
|
22
|
-
|
23
|
-
def format_message(message)
|
24
|
-
case message
|
25
|
-
when ::String
|
26
|
-
message
|
27
|
-
when ::Exception
|
28
|
-
"<#{message.class}>:#{message.message}\n#{(message.backtrace || []).join("\n")}"
|
29
|
-
else
|
30
|
-
message.inspect
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
data/test_usage/test_domain.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require 'bundler/setup'
|
5
|
-
require 'libvirt'
|
6
|
-
require 'logger'
|
7
|
-
require 'active_support/all'
|
8
|
-
require 'async'
|
9
|
-
|
10
|
-
require_relative 'support/libvirt_async'
|
11
|
-
require_relative 'support/log_formatter'
|
12
|
-
|
13
|
-
require 'libvirt/xml'
|
14
|
-
|
15
|
-
Libvirt.logger = Logger.new(STDOUT, formatter: LogFormatter.new)
|
16
|
-
Libvirt.logger.level = ENV['DEBUG'] ? :debug : :info
|
17
|
-
|
18
|
-
IMPL = LibvirtAsync::Implementations.new
|
19
|
-
|
20
|
-
Async do
|
21
|
-
ASYNC_REACTOR = Async::Task.current.reactor
|
22
|
-
|
23
|
-
puts "Lib version #{Libvirt.lib_version}"
|
24
|
-
puts "Gem version #{Libvirt::VERSION}"
|
25
|
-
|
26
|
-
IMPL.start
|
27
|
-
|
28
|
-
conn = Libvirt::Connection.new('qemu+tcp://localhost:16510/system')
|
29
|
-
conn.open
|
30
|
-
|
31
|
-
puts "Connection version #{conn.version.inspect}"
|
32
|
-
puts "Connection lib_version #{conn.lib_version.inspect}"
|
33
|
-
puts "Connection hostname #{conn.hostname.inspect}"
|
34
|
-
|
35
|
-
doms = conn.list_all_domains
|
36
|
-
puts "Connection domains qty #{doms.size}"
|
37
|
-
|
38
|
-
doms.each.with_index do |dom, i|
|
39
|
-
puts "Domain #{i} xml", dom.xml_desc
|
40
|
-
puts "Domain #{i} xml object", Libvirt::Xml::Domain.load(dom.xml_desc).to_h
|
41
|
-
end
|
42
|
-
|
43
|
-
end
|