libvirt_ffi 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|