libvirt_ffi 0.2.1 → 0.3.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/libvirt/connection.rb +12 -4
- data/lib/libvirt/domain.rb +13 -5
- data/lib/libvirt/event.rb +35 -21
- data/lib/libvirt/ffi/domain.rb +8 -0
- data/lib/libvirt/ffi/stream.rb +72 -0
- data/lib/libvirt/stream.rb +97 -0
- data/lib/libvirt/version.rb +1 -1
- data/lib/libvirt.rb +2 -0
- data/test_usage/support/libvirt_async.rb +12 -2
- data/test_usage/test_screenshot.rb +196 -0
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 32cd6d96cd065507a105cffe398c5d6bfa2afd2cd472888f831dd2ad382a48de
|
4
|
+
data.tar.gz: 06ae43ce6d0d65c8d6a5daa0914df5cfa01a3102f467bc7bef3bafaa19e2208a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 205e7bc1253381af45bcf354b784476acf35f862ba212f6a9b7cdeba3673ed2ae5b73b54ec0a894632e753dd8f1e7ba90cec6a40187c1a0c33df6900f4208c71
|
7
|
+
data.tar.gz: d5754a19f39a9c508722b1cb8d29227d38c62eb1c9f0a7503d94aba33f815180217d4b346c32a1e4638a8b1e2526910ebf6dc6ccffe6ab8e3c415870b629b430
|
data/lib/libvirt/connection.rb
CHANGED
@@ -6,9 +6,11 @@ module Libvirt
|
|
6
6
|
@uri = uri
|
7
7
|
@conn_ptr = ::FFI::Pointer.new(0)
|
8
8
|
@cb_data = {}
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
|
10
|
+
free = ->(obj_id) do
|
11
|
+
STDOUT.puts("finalized Libvirt::Connection obj_id=0x#{obj_id.to_s(16)}, @conn_ptr=#{@conn_ptr}, @uri=#{@uri}, @cb_data=#{@cb_data}")
|
12
|
+
end
|
13
|
+
ObjectSpace.define_finalizer(self, free)
|
12
14
|
end
|
13
15
|
|
14
16
|
def open
|
@@ -61,7 +63,7 @@ module Libvirt
|
|
61
63
|
result = FFI::Domain.virConnectListAllDomains(@conn_ptr, domains_ptr, flags)
|
62
64
|
raise Error, "Couldn't retrieve domains list with flags #{flags.to_s(16)}" if result < 0
|
63
65
|
ptr = domains_ptr.read_pointer
|
64
|
-
ptr.get_array_of_pointer(0, size).map { |dom_ptr| Libvirt::Domain.new(dom_ptr
|
66
|
+
ptr.get_array_of_pointer(0, size).map { |dom_ptr| Libvirt::Domain.new(dom_ptr) }
|
65
67
|
end
|
66
68
|
|
67
69
|
# @yield conn, dom
|
@@ -131,6 +133,12 @@ module Libvirt
|
|
131
133
|
NodeInfo.new(node_info_ptr)
|
132
134
|
end
|
133
135
|
|
136
|
+
def stream(flags = 0)
|
137
|
+
pointer = FFI::Stream.virStreamNew(@conn_ptr, flags)
|
138
|
+
raise Error, "Couldn't create stream" if pointer.null?
|
139
|
+
Stream.new(pointer)
|
140
|
+
end
|
141
|
+
|
134
142
|
private
|
135
143
|
|
136
144
|
def check_open!
|
data/lib/libvirt/domain.rb
CHANGED
@@ -2,12 +2,13 @@
|
|
2
2
|
|
3
3
|
module Libvirt
|
4
4
|
class Domain
|
5
|
-
def initialize(dom_ptr
|
5
|
+
def initialize(dom_ptr)
|
6
6
|
@dom_ptr = dom_ptr
|
7
|
-
|
8
|
-
|
9
|
-
STDOUT.puts("finalized Libvirt::Domain #{obj_id.to_s(16)}")
|
10
|
-
|
7
|
+
|
8
|
+
free = ->(obj_id) do
|
9
|
+
STDOUT.puts("finalized Libvirt::Domain obj_id=0x#{obj_id.to_s(16)}, @dom_ptr=#{@dom_ptr},")
|
10
|
+
end
|
11
|
+
ObjectSpace.define_finalizer(self, free)
|
11
12
|
end
|
12
13
|
|
13
14
|
def get_state
|
@@ -56,5 +57,12 @@ module Libvirt
|
|
56
57
|
def xml_desc(flags = 0)
|
57
58
|
FFI::Domain.virDomainGetXMLDesc(@dom_ptr, flags)
|
58
59
|
end
|
60
|
+
|
61
|
+
def screenshot(stream, display = 0)
|
62
|
+
mime_type, pointer = FFI::Domain.virDomainScreenshot(@dom_ptr, stream.to_ptr, display, 0)
|
63
|
+
raise Error, "Couldn't attach domain screenshot" if pointer.null?
|
64
|
+
# free pointer required
|
65
|
+
mime_type
|
66
|
+
end
|
59
67
|
end
|
60
68
|
end
|
data/lib/libvirt/event.rb
CHANGED
@@ -9,24 +9,32 @@ module Libvirt
|
|
9
9
|
extend Forwardable
|
10
10
|
extend SingleForwardable
|
11
11
|
|
12
|
-
single_delegate [
|
12
|
+
single_delegate [
|
13
|
+
:register,
|
14
|
+
:unregister,
|
15
|
+
:registered?,
|
16
|
+
:debug,
|
17
|
+
:debug=,
|
18
|
+
:invoke_handle_callback,
|
19
|
+
:invoke_timeout_callback
|
20
|
+
] => :instance
|
21
|
+
|
22
|
+
attr_accessor :debug
|
13
23
|
|
14
24
|
Opaque = Struct.new(:cb, :opaque, :ff)
|
15
25
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
cb.call(timer, op)
|
29
|
-
end
|
26
|
+
def invoke_handle_callback(watch, fd, events, opaque)
|
27
|
+
cb = opaque.cb
|
28
|
+
op = opaque.opaque
|
29
|
+
dbg { "Libvirt::Event INVOKE_HANDLE_CALLBACK watch=#{watch} fd=#{fd} events=#{events} op=#{op}" }
|
30
|
+
cb.call(watch, fd, events, op)
|
31
|
+
end
|
32
|
+
|
33
|
+
def invoke_timeout_callback(timer, opaque)
|
34
|
+
cb = opaque.cb
|
35
|
+
op = opaque.opaque
|
36
|
+
dbg { "Libvirt::Event INVOKE_TIMEOUT_CALLBACK timer=#{timer} op=#{op}" }
|
37
|
+
cb.call(timer, op)
|
30
38
|
end
|
31
39
|
|
32
40
|
def registered?
|
@@ -80,18 +88,18 @@ module Libvirt
|
|
80
88
|
private
|
81
89
|
|
82
90
|
def _add_handle(fd, event, cb, opaque, ff)
|
83
|
-
|
91
|
+
dbg { "Libvirt::Event ADD_HANDLE fd=#{fd}, #{event}=event, cb=#{cb}, opaque=#{opaque}, ff=#{ff}" }
|
84
92
|
op = Opaque.new(cb, opaque, ff)
|
85
93
|
@add_handle.call(fd, event, op)
|
86
94
|
end
|
87
95
|
|
88
96
|
def _update_handle(watch, event)
|
89
|
-
|
97
|
+
dbg { "Libvirt::Event UPDATE_HANDLE watch=#{watch}, event=#{event}" }
|
90
98
|
@update_handle.call(watch, event)
|
91
99
|
end
|
92
100
|
|
93
101
|
def _remove_handle(watch)
|
94
|
-
|
102
|
+
dbg { "Libvirt::Event REMOVE_HANDLE watch=#{watch}" }
|
95
103
|
op = @remove_handle.call(watch)
|
96
104
|
free_func = op.ff
|
97
105
|
opaque = op.opaque
|
@@ -100,18 +108,18 @@ module Libvirt
|
|
100
108
|
end
|
101
109
|
|
102
110
|
def _add_timer(timeout, cb, opaque, ff)
|
103
|
-
|
111
|
+
dbg { "Libvirt::Event ADD_TIMER timeout=#{timeout}, cb=#{cb}, opaque=#{opaque}, ff=#{ff}" }
|
104
112
|
op = Opaque.new(cb, opaque, ff)
|
105
113
|
@add_timer.call(timeout, op)
|
106
114
|
end
|
107
115
|
|
108
116
|
def _update_timer(timer, timeout)
|
109
|
-
|
117
|
+
dbg { "Libvirt::Event UPDATE_TIMER timer=#{timer}, timeout=#{timeout}" }
|
110
118
|
@update_timer.call(timer, timeout)
|
111
119
|
end
|
112
120
|
|
113
121
|
def _remove_timer(timer)
|
114
|
-
|
122
|
+
dbg { "Libvirt::Event REMOVE_TIMER timer=#{timer}" }
|
115
123
|
op = @remove_timer.call(timer)
|
116
124
|
free_func = op.ff
|
117
125
|
opaque = op.opaque
|
@@ -119,5 +127,11 @@ module Libvirt
|
|
119
127
|
0
|
120
128
|
end
|
121
129
|
|
130
|
+
def dbg(&block)
|
131
|
+
return unless debug
|
132
|
+
|
133
|
+
Util.log(:debug, &block)
|
134
|
+
end
|
135
|
+
|
122
136
|
end
|
123
137
|
end
|
data/lib/libvirt/ffi/domain.rb
CHANGED
@@ -109,6 +109,14 @@ module Libvirt
|
|
109
109
|
# )
|
110
110
|
attach_function :virDomainGetXMLDesc, [:pointer, :uint], :string # strptr?
|
111
111
|
|
112
|
+
# char *virDomainScreenshot (
|
113
|
+
# virDomainPtr domain,
|
114
|
+
# virStreamPtr stream,
|
115
|
+
# unsigned int screen,
|
116
|
+
# unsigned int flags
|
117
|
+
# )
|
118
|
+
attach_function :virDomainScreenshot, [:pointer, :pointer, :uint, :uint], :strptr
|
119
|
+
|
112
120
|
# typedef int (*virConnectDomainEventCallback) (
|
113
121
|
# virConnectPtr conn,
|
114
122
|
# virDomainPtr dom,
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Libvirt
|
4
|
+
module FFI
|
5
|
+
module Stream
|
6
|
+
extend ::FFI::Library
|
7
|
+
ffi_lib Util.library_path
|
8
|
+
|
9
|
+
# virStreamPtr virStreamNew (
|
10
|
+
# virConnectPtr conn,
|
11
|
+
# unsigned int flags
|
12
|
+
# )
|
13
|
+
attach_function :virStreamNew, [:pointer, :uint], :pointer
|
14
|
+
|
15
|
+
# typedef void (*virStreamEventCallback) (
|
16
|
+
# virStreamPtr stream,
|
17
|
+
# int events,
|
18
|
+
# void * opaque
|
19
|
+
# )
|
20
|
+
callback :virStreamEventCallback, [:pointer, :int, :pointer], :void
|
21
|
+
|
22
|
+
# int virStreamEventAddCallback (
|
23
|
+
# virStreamPtr stream,
|
24
|
+
# int events,
|
25
|
+
# virStreamEventCallback cb,
|
26
|
+
# void * opaque,
|
27
|
+
# virFreeCallback ff
|
28
|
+
# )
|
29
|
+
attach_function :virStreamEventAddCallback, [
|
30
|
+
:pointer,
|
31
|
+
:int,
|
32
|
+
:virStreamEventCallback,
|
33
|
+
:pointer,
|
34
|
+
FFI::Common::FREE_CALLBACK
|
35
|
+
], :int
|
36
|
+
|
37
|
+
# int virStreamEventRemoveCallback (
|
38
|
+
# virStreamPtr stream
|
39
|
+
# )
|
40
|
+
attach_function :virStreamEventRemoveCallback, [:pointer], :int
|
41
|
+
|
42
|
+
# int virStreamEventUpdateCallback (
|
43
|
+
# virStreamPtr stream,
|
44
|
+
# int events
|
45
|
+
# )
|
46
|
+
attach_function :virStreamEventUpdateCallback, [:pointer, :int], :int
|
47
|
+
|
48
|
+
# int virStreamFinish (
|
49
|
+
# virStreamPtr stream
|
50
|
+
# )
|
51
|
+
attach_function :virStreamFinish, [:pointer], :int
|
52
|
+
|
53
|
+
# int virStreamFree (
|
54
|
+
# virStreamPtr stream
|
55
|
+
# )
|
56
|
+
attach_function :virStreamFree, [:pointer], :int
|
57
|
+
|
58
|
+
# int virStreamAbort (
|
59
|
+
# virStreamPtr stream
|
60
|
+
# )
|
61
|
+
attach_function :virStreamAbort, [:pointer], :int
|
62
|
+
|
63
|
+
# int virStreamRecv (
|
64
|
+
# virStreamPtr stream,
|
65
|
+
# char *data,
|
66
|
+
# size_t nbytes
|
67
|
+
# )
|
68
|
+
attach_function :virStreamRecv, [:pointer, :pointer, :size_t], :int
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Libvirt
|
4
|
+
class Stream
|
5
|
+
NONBLOCK = 0x1
|
6
|
+
EVENT_READABLE = 0x1
|
7
|
+
EVENT_WRITABLE = 0x2
|
8
|
+
|
9
|
+
def initialize(stream_ptr)
|
10
|
+
@stream_ptr = stream_ptr
|
11
|
+
@cb = nil
|
12
|
+
@opaque = nil
|
13
|
+
|
14
|
+
free = ->(obj_id) do
|
15
|
+
STDOUT.puts("finalized Libvirt::Stream obj_id=0x#{obj_id.to_s(16)}, @stream_ptr=#{@stream_ptr}, @cb=#{@cb},")
|
16
|
+
if @stream_ptr && @cb
|
17
|
+
rm = FFI::Stream.virStreamEventRemoveCallback(@stream_ptr)
|
18
|
+
STDOUT.puts("finalized Libvirt::Stream obj_id=0x#{obj_id.to_s(16)} rm=#{rm}")
|
19
|
+
ab = FFI::Stream.virStreamAbort(@stream_ptr)
|
20
|
+
STDOUT.puts("finalized Libvirt::Stream obj_id=0x#{obj_id.to_s(16)} ab=#{ab}")
|
21
|
+
end
|
22
|
+
fr = FFI::Stream.virStreamFree(@stream_ptr) if @stream_ptr
|
23
|
+
STDOUT.puts("finalized Libvirt::Stream obj_id=0x#{obj_id.to_s(16)} fr=#{fr}")
|
24
|
+
end
|
25
|
+
ObjectSpace.define_finalizer(self, free)
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_ptr
|
29
|
+
@stream_ptr
|
30
|
+
end
|
31
|
+
|
32
|
+
# @param events [Integer] bit OR of EVENT_READABLE, EVENT_READABLE
|
33
|
+
# @param opaque [Object]
|
34
|
+
# @yield [Stream]
|
35
|
+
def event_add_callback(events, opaque, &block)
|
36
|
+
raise Error, 'callback already added' unless @cb.nil?
|
37
|
+
|
38
|
+
@opaque = opaque
|
39
|
+
@cb = ::FFI::Function.new(:void, [:pointer, :int, :pointer]) do |_stream_ptr, evs, _op|
|
40
|
+
# stream = Stream.new(stream_ptr)
|
41
|
+
block.call(self, evs, @opaque)
|
42
|
+
end
|
43
|
+
|
44
|
+
result = FFI::Stream.virStreamEventAddCallback(@stream_ptr, events, @cb, nil, nil)
|
45
|
+
raise Error, "Couldn't add stream event callback" if result < 0
|
46
|
+
|
47
|
+
true
|
48
|
+
end
|
49
|
+
|
50
|
+
# @param events [Integer] bit OR of EVENT_READABLE, EVENT_READABLE
|
51
|
+
def event_update_callback(events)
|
52
|
+
result = FFI::Stream.virStreamEventUpdateCallback(@stream_ptr, events)
|
53
|
+
raise Error, "Couldn't remove stream event callback" if result < 0
|
54
|
+
true
|
55
|
+
end
|
56
|
+
|
57
|
+
def event_remove_callback
|
58
|
+
result = FFI::Stream.virStreamEventRemoveCallback(@stream_ptr)
|
59
|
+
raise Error, "Couldn't remove stream event callback" if result < 0
|
60
|
+
opaque = @opaque
|
61
|
+
@cb = nil
|
62
|
+
@opaque = nil
|
63
|
+
opaque
|
64
|
+
end
|
65
|
+
|
66
|
+
def finish
|
67
|
+
result = FFI::Stream.virStreamFinish(@stream_ptr)
|
68
|
+
raise Error, "Couldn't remove stream event callback" if result < 0
|
69
|
+
@cb = nil
|
70
|
+
@opaque = nil
|
71
|
+
end
|
72
|
+
|
73
|
+
def abort_stream
|
74
|
+
result = FFI::Stream.virStreamAbort(@stream_ptr)
|
75
|
+
raise Error, "Couldn't remove stream event callback" if result < 0
|
76
|
+
@cb = nil
|
77
|
+
@opaque = nil
|
78
|
+
end
|
79
|
+
|
80
|
+
def recv(bytes)
|
81
|
+
buffer = ::FFI::MemoryPointer.new(:char, bytes)
|
82
|
+
result = FFI::Stream.virStreamRecv(@stream_ptr, buffer, bytes)
|
83
|
+
if result == -1
|
84
|
+
abort_stream
|
85
|
+
[-1, nil]
|
86
|
+
elsif result == 0
|
87
|
+
[0, nil]
|
88
|
+
elsif result == -2
|
89
|
+
[-2, nil]
|
90
|
+
elsif result > 0
|
91
|
+
[result, buffer.read_bytes(result)]
|
92
|
+
else
|
93
|
+
raise Error, "Invalid response from virStreamRecv #{result.inspect}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/lib/libvirt/version.rb
CHANGED
data/lib/libvirt.rb
CHANGED
@@ -10,10 +10,12 @@ require 'libvirt/ffi/connection'
|
|
10
10
|
require 'libvirt/ffi/domain'
|
11
11
|
require 'libvirt/ffi/event'
|
12
12
|
require 'libvirt/ffi/node_info'
|
13
|
+
require 'libvirt/ffi/stream'
|
13
14
|
require 'libvirt/event'
|
14
15
|
require 'libvirt/connection'
|
15
16
|
require 'libvirt/domain'
|
16
17
|
require 'libvirt/node_info'
|
18
|
+
require 'libvirt/stream'
|
17
19
|
require 'libvirt/version'
|
18
20
|
|
19
21
|
module Libvirt
|
@@ -1,17 +1,27 @@
|
|
1
1
|
module LibvirtAsync
|
2
|
+
class << self
|
3
|
+
def logger=(logger)
|
4
|
+
@logger = logger
|
5
|
+
end
|
6
|
+
|
7
|
+
def logger
|
8
|
+
@logger
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
2
12
|
module WithDbg
|
3
13
|
extend ActiveSupport::Concern
|
4
14
|
|
5
15
|
class_methods do
|
6
16
|
def dbg(progname = nil, &block)
|
7
|
-
|
17
|
+
LibvirtAsync.logger&.debug(progname || "#{name}.:0x#{object_id.to_s(16)}", &block)
|
8
18
|
end
|
9
19
|
end
|
10
20
|
|
11
21
|
private
|
12
22
|
|
13
23
|
def dbg(progname = nil, &block)
|
14
|
-
|
24
|
+
LibvirtAsync.logger&.debug(progname || "#{self.class}#:0x#{object_id.to_s(16)}", &block)
|
15
25
|
end
|
16
26
|
end
|
17
27
|
|
@@ -0,0 +1,196 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'libvirt'
|
5
|
+
require 'logger'
|
6
|
+
require 'active_support/all'
|
7
|
+
require 'async'
|
8
|
+
require 'get_process_mem'
|
9
|
+
|
10
|
+
require_relative 'support/libvirt_async'
|
11
|
+
require_relative 'support/log_formatter'
|
12
|
+
|
13
|
+
Libvirt.logger = Logger.new(STDOUT, formatter: LogFormatter.new)
|
14
|
+
Libvirt.logger.level = ENV['DEBUG'] ? :debug : :info
|
15
|
+
|
16
|
+
LibvirtAsync.logger = Logger.new(STDOUT, formatter: LogFormatter.new)
|
17
|
+
LibvirtAsync.logger.level = ENV['LIBVIRT_DEBUG'] ? :debug : :info
|
18
|
+
|
19
|
+
def print_usage(msg)
|
20
|
+
mem = GetProcessMem.new
|
21
|
+
STDOUT.puts "#{msg} [#{mem.mb}MB]"
|
22
|
+
end
|
23
|
+
|
24
|
+
def run_gc(msg)
|
25
|
+
print_usage "#{msg} before GC.start"
|
26
|
+
GC.start
|
27
|
+
print_usage "#{msg} after GC.start"
|
28
|
+
end
|
29
|
+
|
30
|
+
IMPL = LibvirtAsync::Implementations.new
|
31
|
+
CONNS = []
|
32
|
+
DOMS = []
|
33
|
+
STREAMS = { stream: nil }
|
34
|
+
|
35
|
+
class ScreenshotOpaque
|
36
|
+
CALLBACK = proc do |s, ev, op|
|
37
|
+
#run_gc('ScreenshotOpaque CALLBACK start')
|
38
|
+
next unless (Libvirt::Stream::EVENT_READABLE & ev) != 0
|
39
|
+
begin
|
40
|
+
code, data = s.recv(1024)
|
41
|
+
rescue Libvirt::Error => e
|
42
|
+
op.on_libvirt_error(s, e)
|
43
|
+
next
|
44
|
+
end
|
45
|
+
#run_gc('ScreenshotOpaque CALLBACK after recv')
|
46
|
+
|
47
|
+
case code
|
48
|
+
when 0
|
49
|
+
op.on_complete(s)
|
50
|
+
when -1
|
51
|
+
op.on_recv_error(s)
|
52
|
+
when -2
|
53
|
+
print_usage "Opaque::CALLBACK #{op.filepath} wait for data"
|
54
|
+
else
|
55
|
+
op.on_receive(data)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
attr_reader :filepath
|
60
|
+
|
61
|
+
def initialize(filepath, finish_cb)
|
62
|
+
@filepath = filepath
|
63
|
+
@f = File.open(@filepath, 'wb')
|
64
|
+
@finish_cb = finish_cb
|
65
|
+
end
|
66
|
+
|
67
|
+
def on_complete(stream)
|
68
|
+
print_usage "Opaque#on_complete #{@filepath}"
|
69
|
+
success, reason = finish_stream(stream)
|
70
|
+
finish(success, reason)
|
71
|
+
end
|
72
|
+
|
73
|
+
def on_receive(data)
|
74
|
+
print_usage "Opaque#on_receive #{@filepath} #{data&.size}"
|
75
|
+
@f.write(data)
|
76
|
+
end
|
77
|
+
|
78
|
+
def on_recv_error(stream)
|
79
|
+
print_usage "Opaque#on_recv_error #{@filepath}"
|
80
|
+
success, reason = finish_stream(stream)
|
81
|
+
finish(success, reason)
|
82
|
+
end
|
83
|
+
|
84
|
+
def on_libvirt_error(stream, e)
|
85
|
+
print_usage "Opaque#on_libvirt_error #{@filepath} #{e}"
|
86
|
+
success, reason = finish_stream(stream)
|
87
|
+
finish(success, reason)
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def finish_stream(stream)
|
93
|
+
print_usage "Opaque#finish_stream stream.event_remove_callback #{@filepath}"
|
94
|
+
stream.event_remove_callback
|
95
|
+
result = begin
|
96
|
+
print_usage "Opaque#finish_stream stream.finish #{@filepath}"
|
97
|
+
stream.finish
|
98
|
+
[true, nil]
|
99
|
+
rescue Libvirt::Error => e
|
100
|
+
STDERR.puts "Opaque#finish_stream stream.finish exception rescued #{e.class} #{e.message}"
|
101
|
+
[false, e.message]
|
102
|
+
end
|
103
|
+
print_usage "Opaque#finish_stream ends #{@filepath}"
|
104
|
+
result
|
105
|
+
end
|
106
|
+
|
107
|
+
def finish(success, reason)
|
108
|
+
print_usage "Opaque#finish success=#{success} #{@filepath}"
|
109
|
+
|
110
|
+
@f.close
|
111
|
+
@f = nil
|
112
|
+
@finish_cb.call(success, reason)
|
113
|
+
@finish_cb = nil
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def save_screenshot(c, domain, i)
|
118
|
+
stream = c.stream(Libvirt::Stream::NONBLOCK)
|
119
|
+
|
120
|
+
opaque_cb = proc do |success|
|
121
|
+
puts "Stream #{i} complete success=#{success}"
|
122
|
+
print_usage "after stream #{i} complete stream=#{STREAMS["stream#{i}"]}"
|
123
|
+
run_gc("Stream #{i} complete before remove stream")
|
124
|
+
print_usage "after stream #{i} complete and GC.start"
|
125
|
+
STREAMS["stream#{i}"] = nil
|
126
|
+
run_gc("Stream #{i} complete before remove stream")
|
127
|
+
print_usage "after stream #{i} delete and GC.start"
|
128
|
+
end
|
129
|
+
|
130
|
+
opaque = ScreenshotOpaque.new("tmp/screenshots_test#{i}.pnm", opaque_cb)
|
131
|
+
|
132
|
+
STREAMS["stream#{i}"] = stream
|
133
|
+
|
134
|
+
print_usage "test_screenshot_mem #{i} before stream start"
|
135
|
+
domain.screenshot(stream, 0)
|
136
|
+
stream.event_add_callback(
|
137
|
+
Libvirt::Stream::EVENT_READABLE,
|
138
|
+
opaque,
|
139
|
+
&ScreenshotOpaque::CALLBACK
|
140
|
+
)
|
141
|
+
run_gc("Stream #{i} after add event")
|
142
|
+
end
|
143
|
+
|
144
|
+
Async do
|
145
|
+
ASYNC_REACTOR = Async::Task.current.reactor
|
146
|
+
|
147
|
+
puts "Lib version #{Libvirt.lib_version}"
|
148
|
+
puts "Gem version #{Libvirt::VERSION}"
|
149
|
+
|
150
|
+
IMPL.start
|
151
|
+
|
152
|
+
c = Libvirt::Connection.new('qemu+tcp://localhost:16510/system')
|
153
|
+
c.open
|
154
|
+
res = c.set_keep_alive(2, 1)
|
155
|
+
Libvirt.logger.info { "set_keep_alive #{res}" }
|
156
|
+
CONNS.push(c)
|
157
|
+
|
158
|
+
domain = c.list_all_domains.first
|
159
|
+
DOMS.push(domain)
|
160
|
+
|
161
|
+
print_usage "First generation"
|
162
|
+
5.times do |i|
|
163
|
+
save_screenshot(c, domain, 100 + i)
|
164
|
+
end
|
165
|
+
|
166
|
+
ASYNC_REACTOR.after(15) do
|
167
|
+
Async::Task.new(ASYNC_REACTOR, nil) do
|
168
|
+
print_usage "Second generation"
|
169
|
+
|
170
|
+
con = CONNS.first
|
171
|
+
dom = DOMS.first
|
172
|
+
5.times do |i|
|
173
|
+
save_screenshot(con, dom, 200 + i)
|
174
|
+
end
|
175
|
+
end.run
|
176
|
+
end
|
177
|
+
|
178
|
+
ASYNC_REACTOR.after(30) do
|
179
|
+
Async::Task.new(ASYNC_REACTOR, nil) do
|
180
|
+
print_usage "Third generation"
|
181
|
+
|
182
|
+
con = CONNS.first
|
183
|
+
dom = DOMS.first
|
184
|
+
5.times do |i|
|
185
|
+
save_screenshot(con, dom, 300 + i)
|
186
|
+
end
|
187
|
+
end.run
|
188
|
+
end
|
189
|
+
|
190
|
+
ASYNC_REACTOR.every(5) do
|
191
|
+
Async::Task.new(ASYNC_REACTOR, nil) do
|
192
|
+
run_gc 'PERIODIC'
|
193
|
+
end.run
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: libvirt_ffi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Denis Talakevich
|
@@ -53,7 +53,9 @@ files:
|
|
53
53
|
- lib/libvirt/ffi/event.rb
|
54
54
|
- lib/libvirt/ffi/libvirt.rb
|
55
55
|
- lib/libvirt/ffi/node_info.rb
|
56
|
+
- lib/libvirt/ffi/stream.rb
|
56
57
|
- lib/libvirt/node_info.rb
|
58
|
+
- lib/libvirt/stream.rb
|
57
59
|
- lib/libvirt/util.rb
|
58
60
|
- lib/libvirt/version.rb
|
59
61
|
- lib/libvirt_ffi.rb
|
@@ -61,6 +63,7 @@ files:
|
|
61
63
|
- test_usage/support/libvirt_async.rb
|
62
64
|
- test_usage/support/log_formatter.rb
|
63
65
|
- test_usage/test_event_loop.rb
|
66
|
+
- test_usage/test_screenshot.rb
|
64
67
|
homepage: https://github.com/senid231/libvirt_ffi
|
65
68
|
licenses:
|
66
69
|
- MIT
|