libvirt_ffi 0.2.1 → 0.5.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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +78 -0
  3. data/Gemfile +7 -2
  4. data/Rakefile +6 -1
  5. data/bin/console +1 -0
  6. data/exe/libvirt +1 -0
  7. data/lib/libvirt.rb +14 -13
  8. data/lib/libvirt/base_info.rb +34 -0
  9. data/lib/libvirt/connection.rb +156 -47
  10. data/lib/libvirt/domain.rb +136 -8
  11. data/lib/libvirt/domain_callback_storage.rb +69 -0
  12. data/lib/libvirt/errors.rb +65 -0
  13. data/lib/libvirt/event.rb +60 -38
  14. data/lib/libvirt/ffi.rb +17 -0
  15. data/lib/libvirt/ffi/common.rb +8 -1
  16. data/lib/libvirt/ffi/domain.rb +796 -69
  17. data/lib/libvirt/ffi/error.rb +243 -0
  18. data/lib/libvirt/ffi/event.rb +30 -36
  19. data/lib/libvirt/ffi/helpers.rb +17 -0
  20. data/lib/libvirt/ffi/host.rb +122 -0
  21. data/lib/libvirt/ffi/storage.rb +149 -0
  22. data/lib/libvirt/ffi/stream.rb +74 -0
  23. data/lib/libvirt/node_info.rb +2 -41
  24. data/lib/libvirt/storage_pool.rb +70 -0
  25. data/lib/libvirt/storage_pool_info.rb +7 -0
  26. data/lib/libvirt/storage_volume.rb +51 -0
  27. data/lib/libvirt/storage_volume_info.rb +7 -0
  28. data/lib/libvirt/stream.rb +124 -0
  29. data/lib/libvirt/util.rb +75 -8
  30. data/lib/libvirt/version.rb +1 -1
  31. data/lib/libvirt/xml.rb +23 -0
  32. data/lib/libvirt/xml/disk.rb +59 -0
  33. data/lib/libvirt/xml/domain.rb +76 -0
  34. data/lib/libvirt/xml/generic.rb +252 -0
  35. data/lib/libvirt/xml/graphics.rb +14 -0
  36. data/lib/libvirt/xml/max_vcpu.rb +12 -0
  37. data/lib/libvirt/xml/memory.rb +14 -0
  38. data/lib/libvirt/xml/storage_pool.rb +24 -0
  39. data/lib/libvirt/xml/storage_volume.rb +32 -0
  40. data/lib/libvirt/xml/vcpu.rb +12 -0
  41. data/lib/libvirt_ffi.rb +2 -0
  42. data/libvirt.gemspec +5 -1
  43. data/test_usage/support/libvirt_async.rb +33 -31
  44. data/test_usage/support/log_formatter.rb +5 -10
  45. data/test_usage/test_domain.rb +43 -0
  46. data/test_usage/test_event_loop.rb +134 -33
  47. data/test_usage/test_libvirtd_restart.rb +63 -0
  48. data/test_usage/test_metadata.rb +104 -0
  49. data/test_usage/test_screenshot.rb +197 -0
  50. data/test_usage/test_storage.rb +52 -0
  51. metadata +46 -6
  52. data/lib/libvirt/error.rb +0 -6
  53. data/lib/libvirt/ffi/connection.rb +0 -84
  54. data/lib/libvirt/ffi/libvirt.rb +0 -17
  55. data/lib/libvirt/ffi/node_info.rb +0 -37
@@ -0,0 +1,63 @@
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
+ require 'get_process_mem'
10
+ require 'gc_tracer'
11
+
12
+ require_relative 'support/libvirt_async'
13
+ require_relative 'support/log_formatter'
14
+
15
+ GC::Tracer.start_logging(
16
+ nil,
17
+ gc_stat: false,
18
+ gc_latest_gc_info: false,
19
+ rusage: false,
20
+ events: [:end_mark, :end_sweep]
21
+ )
22
+
23
+ Libvirt.logger = Logger.new(STDOUT, formatter: LogFormatter.new)
24
+ Libvirt.logger.level = ENV['DEBUG'] ? :debug : :info
25
+
26
+ IMPL = LibvirtAsync::Implementations.new
27
+ OBJECTS = {
28
+ hv: nil
29
+ }.freeze
30
+
31
+ def async_task(run, parent = nil, &block)
32
+ task = LibvirtAsync::Util.create_task(parent, ASYNC_REACTOR, &block)
33
+ case run
34
+ when :now
35
+ task.run
36
+ when :later
37
+ task.reactor << task.fiber
38
+ else
39
+ raise ArgumentError, "invalid run #{run}"
40
+ end
41
+ end
42
+
43
+ Async do
44
+ ASYNC_REACTOR = Async::Task.current.reactor
45
+
46
+ puts "Lib version #{Libvirt.lib_version}"
47
+ puts "Gem version #{Libvirt::VERSION}"
48
+
49
+ IMPL.start
50
+
51
+ OBJECTS[:hv] = Libvirt::Connection.new('qemu+tcp://localhost:16510/system')
52
+ OBJECTS[:hv].open
53
+ OBJECTS[:hv].register_close_callback do |conn, reason, _op|
54
+ puts "Im closing conn=#{conn}, reason=#{reason}"
55
+ end
56
+ # OBJECTS[:hv].set_keep_alive(2, 1)
57
+
58
+ ASYNC_REACTOR.every(5) do
59
+ async_task(:now) do
60
+ puts "list_all_domains_qty #{OBJECTS[:hv].list_all_domains_qty}"
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,104 @@
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
+ STDOUT.sync = true
21
+ STDERR.sync = true
22
+
23
+ def log_error(error, skip_backtrace: false, causes: [])
24
+ STDERR.puts "<#{error.class}>: #{error.message}", error.backtrace
25
+ if error.cause && error.cause != error && !causes.include?(error.cause)
26
+ causes.push(error)
27
+ log_error(error.cause, skip_backtrace: skip_backtrace, causes: causes)
28
+ end
29
+ end
30
+
31
+ def libvirt_safe(rescue_value = nil)
32
+ yield
33
+ rescue Libvirt::Errors::LibError => e
34
+ STDERR.puts "<#{e.class}>: #{e.message}"
35
+ rescue_value
36
+ end
37
+
38
+ Async do
39
+ ASYNC_REACTOR = Async::Task.current.reactor
40
+
41
+ puts "Lib version #{Libvirt.lib_version}"
42
+ puts "Gem version #{Libvirt::VERSION}"
43
+
44
+ IMPL.start
45
+
46
+ conn = Libvirt::Connection.new('qemu+tcp://localhost:16510/system')
47
+ conn.open
48
+
49
+ puts "Connection version #{conn.version.inspect}"
50
+ puts "Connection lib_version #{conn.lib_version.inspect}"
51
+ puts "Connection hostname #{conn.hostname.inspect}"
52
+
53
+ dom = conn.list_all_domains.first
54
+ puts "Domain #{dom.uuid} #{dom.name} #{dom.get_state}"
55
+
56
+ libvirt_safe do
57
+ dom.start
58
+ end
59
+
60
+ dom.set_metadata("test title #{Process.pid}", type: :TITLE, flags: :AFFECT_CONFIG)
61
+ dom.set_metadata("test desc #{Process.pid}", type: :DESCRIPTION, flags: :AFFECT_CONFIG)
62
+
63
+ puts "domain title", libvirt_safe{ dom.get_metadata(type: :TITLE, flags: :AFFECT_CONFIG) }
64
+ puts "domain description", libvirt_safe { dom.get_metadata(type: :DESCRIPTION, flags: :AFFECT_CONFIG) }
65
+
66
+ puts "full XML title", Libvirt::Xml::Domain.load(dom.xml_desc).title
67
+ puts "full XML description", Libvirt::Xml::Domain.load(dom.xml_desc).description
68
+
69
+ namespace = 'https://example.com'
70
+ old_metadata = dom.get_metadata(
71
+ uri: namespace, flags: :AFFECT_CONFIG
72
+ )
73
+
74
+ puts "Old Metadata", old_metadata
75
+
76
+ new_metadata = "<pid>#{Process.pid}</pid>"
77
+ key = 'example'
78
+ dom.set_metadata new_metadata,
79
+ key: key,
80
+ uri: namespace,
81
+ flags: :AFFECT_CONFIG
82
+
83
+ puts "new metadata", dom.get_metadata(
84
+ uri: namespace, flags: :AFFECT_CONFIG
85
+ )
86
+
87
+ puts "full XML metadata", Libvirt::Xml::Domain.load(dom.xml_desc).metadata
88
+
89
+ puts "domain shutdown", libvirt_safe { dom.shutdown }
90
+ ASYNC_REACTOR.sleep 5
91
+ puts dom.get_state
92
+
93
+ puts "domain start", libvirt_safe { dom.start }
94
+ ASYNC_REACTOR.sleep 2
95
+ puts dom.get_state
96
+
97
+ puts "full XML metadata", Libvirt::Xml::Domain.load(dom.xml_desc).metadata
98
+ puts "full XML title", Libvirt::Xml::Domain.load(dom.xml_desc).title
99
+ puts "full XML description", Libvirt::Xml::Domain.load(dom.xml_desc).description
100
+
101
+ rescue StandardError => e
102
+ log_error(e)
103
+ exit 1
104
+ end
@@ -0,0 +1,197 @@
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
+ require 'get_process_mem'
10
+
11
+ require_relative 'support/libvirt_async'
12
+ require_relative 'support/log_formatter'
13
+
14
+ Libvirt.logger = Logger.new(STDOUT, formatter: LogFormatter.new)
15
+ Libvirt.logger.level = ENV['DEBUG'] ? :debug : :info
16
+
17
+ LibvirtAsync.logger = Logger.new(STDOUT, formatter: LogFormatter.new)
18
+ LibvirtAsync.logger.level = ENV['LIBVIRT_DEBUG'] ? :debug : :info
19
+
20
+ def print_usage(msg)
21
+ mem = GetProcessMem.new
22
+ STDOUT.puts "#{msg} [#{mem.mb}MB]"
23
+ end
24
+
25
+ def run_gc(msg)
26
+ print_usage "#{msg} before GC.start"
27
+ GC.start
28
+ print_usage "#{msg} after GC.start"
29
+ end
30
+
31
+ IMPL = LibvirtAsync::Implementations.new
32
+ CONNS = [].freeze
33
+ DOMS = [].freeze
34
+ STREAMS = { stream: nil }.freeze
35
+
36
+ class ScreenshotOpaque
37
+ CALLBACK = proc do |s, ev, op|
38
+ # run_gc('ScreenshotOpaque CALLBACK start')
39
+ next unless (Libvirt::Stream::EVENT_READABLE & ev) != 0
40
+
41
+ begin
42
+ code, data = s.recv(1024)
43
+ rescue Libvirt::Errors::LibError => e
44
+ op.on_libvirt_error(s, e)
45
+ next
46
+ end
47
+ # run_gc('ScreenshotOpaque CALLBACK after recv')
48
+
49
+ case code
50
+ when 0
51
+ op.on_complete(s)
52
+ when -1
53
+ op.on_recv_error(s)
54
+ when -2
55
+ print_usage "Opaque::CALLBACK #{op.filepath} wait for data"
56
+ else
57
+ op.on_receive(data)
58
+ end
59
+ end
60
+
61
+ attr_reader :filepath
62
+
63
+ def initialize(filepath, finish_cb)
64
+ @filepath = filepath
65
+ @f = File.open(@filepath, 'wb')
66
+ @finish_cb = finish_cb
67
+ end
68
+
69
+ def on_complete(stream)
70
+ print_usage "Opaque#on_complete #{@filepath}"
71
+ success, reason = finish_stream(stream)
72
+ finish(success, reason)
73
+ end
74
+
75
+ def on_receive(data)
76
+ print_usage "Opaque#on_receive #{@filepath} #{data&.size}"
77
+ @f.write(data)
78
+ end
79
+
80
+ def on_recv_error(stream)
81
+ print_usage "Opaque#on_recv_error #{@filepath}"
82
+ success, reason = finish_stream(stream)
83
+ finish(success, reason)
84
+ end
85
+
86
+ def on_libvirt_error(stream, e)
87
+ print_usage "Opaque#on_libvirt_error #{@filepath} #{e}"
88
+ success, reason = finish_stream(stream)
89
+ finish(success, reason)
90
+ end
91
+
92
+ private
93
+
94
+ def finish_stream(stream)
95
+ print_usage "Opaque#finish_stream stream.event_remove_callback #{@filepath}"
96
+ stream.event_remove_callback
97
+ result = begin
98
+ print_usage "Opaque#finish_stream stream.finish #{@filepath}"
99
+ stream.finish
100
+ [true, nil]
101
+ rescue Libvirt::Errors::LibError => e
102
+ warn "Opaque#finish_stream stream.finish exception rescued #{e.class} #{e.message}"
103
+ [false, e.message]
104
+ end
105
+ print_usage "Opaque#finish_stream ends #{@filepath}"
106
+ result
107
+ end
108
+
109
+ def finish(success, reason)
110
+ print_usage "Opaque#finish success=#{success} #{@filepath}"
111
+
112
+ @f.close
113
+ @f = nil
114
+ @finish_cb.call(success, reason)
115
+ @finish_cb = nil
116
+ end
117
+ end
118
+
119
+ def save_screenshot(c, domain, i)
120
+ stream = c.stream(Libvirt::Stream::NONBLOCK)
121
+
122
+ opaque_cb = proc do |success|
123
+ puts "Stream #{i} complete success=#{success}"
124
+ print_usage "after stream #{i} complete stream=#{STREAMS["stream#{i}"]}"
125
+ run_gc("Stream #{i} complete before remove stream")
126
+ print_usage "after stream #{i} complete and GC.start"
127
+ STREAMS["stream#{i}"] = nil
128
+ run_gc("Stream #{i} complete before remove stream")
129
+ print_usage "after stream #{i} delete and GC.start"
130
+ end
131
+
132
+ opaque = ScreenshotOpaque.new("tmp/screenshots_test#{i}.pnm", opaque_cb)
133
+
134
+ STREAMS["stream#{i}"] = stream
135
+
136
+ print_usage "test_screenshot_mem #{i} before stream start"
137
+ domain.screenshot(stream, 0)
138
+ stream.event_add_callback(
139
+ Libvirt::Stream::EVENT_READABLE,
140
+ opaque,
141
+ &ScreenshotOpaque::CALLBACK
142
+ )
143
+ run_gc("Stream #{i} after add event")
144
+ end
145
+
146
+ Async do
147
+ ASYNC_REACTOR = Async::Task.current.reactor
148
+
149
+ puts "Lib version #{Libvirt.lib_version}"
150
+ puts "Gem version #{Libvirt::VERSION}"
151
+
152
+ IMPL.start
153
+
154
+ c = Libvirt::Connection.new('qemu+tcp://localhost:16510/system')
155
+ c.open
156
+ res = c.set_keep_alive(2, 1)
157
+ Libvirt.logger.info { "set_keep_alive #{res}" }
158
+ CONNS.push(c)
159
+
160
+ domain = c.list_all_domains.first
161
+ DOMS.push(domain)
162
+
163
+ print_usage 'First generation'
164
+ 5.times do |i|
165
+ save_screenshot(c, domain, 100 + i)
166
+ end
167
+
168
+ ASYNC_REACTOR.after(15) do
169
+ Async::Task.new(ASYNC_REACTOR, nil) do
170
+ print_usage 'Second generation'
171
+
172
+ con = CONNS.first
173
+ dom = DOMS.first
174
+ 5.times do |i|
175
+ save_screenshot(con, dom, 200 + i)
176
+ end
177
+ end.run
178
+ end
179
+
180
+ ASYNC_REACTOR.after(30) do
181
+ Async::Task.new(ASYNC_REACTOR, nil) do
182
+ print_usage 'Third generation'
183
+
184
+ con = CONNS.first
185
+ dom = DOMS.first
186
+ 5.times do |i|
187
+ save_screenshot(con, dom, 300 + i)
188
+ end
189
+ end.run
190
+ end
191
+
192
+ ASYNC_REACTOR.every(5) do
193
+ Async::Task.new(ASYNC_REACTOR, nil) do
194
+ run_gc 'PERIODIC'
195
+ end.run
196
+ end
197
+ end
@@ -0,0 +1,52 @@
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
+ pools = conn.list_all_storage_pools
36
+ puts "Connection storage pools qty #{pools.size}"
37
+
38
+ pools.each.with_index do |pool, i|
39
+ puts "Storage pool #{i} info", pool.info.to_h
40
+ puts "Storage pool #{i} xml", Libvirt::Xml::StoragePool.load(pool.xml_desc).to_h
41
+ end
42
+
43
+ pools.each.with_index do |pool, i|
44
+ volumes = pool.list_all_volumes
45
+ puts "Storage pool #{i} volumes qty #{volumes.size}"
46
+
47
+ volumes.each.with_index do |vol, j|
48
+ puts "Storage pool #{i} volume #{j} info", vol.info.to_h
49
+ puts "Storage pool #{i} volume #{j} xml", Libvirt::Xml::StorageVolume.load(vol.xml_desc).to_h
50
+ end
51
+ end
52
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libvirt_ffi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis Talakevich
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-01-28 00:00:00.000000000 Z
11
+ date: 2020-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubocop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.80.1
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.80.1
27
41
  description: Libvirt FFI
28
42
  email:
29
43
  - senid231@gmail.com
@@ -33,6 +47,7 @@ extensions: []
33
47
  extra_rdoc_files: []
34
48
  files:
35
49
  - ".gitignore"
50
+ - ".rubocop.yml"
36
51
  - ".travis.yml"
37
52
  - CODE_OF_CONDUCT.md
38
53
  - Gemfile
@@ -43,24 +58,49 @@ files:
43
58
  - bin/setup
44
59
  - exe/libvirt
45
60
  - lib/libvirt.rb
61
+ - lib/libvirt/base_info.rb
46
62
  - lib/libvirt/connection.rb
47
63
  - lib/libvirt/domain.rb
48
- - lib/libvirt/error.rb
64
+ - lib/libvirt/domain_callback_storage.rb
65
+ - lib/libvirt/errors.rb
49
66
  - lib/libvirt/event.rb
67
+ - lib/libvirt/ffi.rb
50
68
  - lib/libvirt/ffi/common.rb
51
- - lib/libvirt/ffi/connection.rb
52
69
  - lib/libvirt/ffi/domain.rb
70
+ - lib/libvirt/ffi/error.rb
53
71
  - lib/libvirt/ffi/event.rb
54
- - lib/libvirt/ffi/libvirt.rb
55
- - lib/libvirt/ffi/node_info.rb
72
+ - lib/libvirt/ffi/helpers.rb
73
+ - lib/libvirt/ffi/host.rb
74
+ - lib/libvirt/ffi/storage.rb
75
+ - lib/libvirt/ffi/stream.rb
56
76
  - lib/libvirt/node_info.rb
77
+ - lib/libvirt/storage_pool.rb
78
+ - lib/libvirt/storage_pool_info.rb
79
+ - lib/libvirt/storage_volume.rb
80
+ - lib/libvirt/storage_volume_info.rb
81
+ - lib/libvirt/stream.rb
57
82
  - lib/libvirt/util.rb
58
83
  - lib/libvirt/version.rb
84
+ - lib/libvirt/xml.rb
85
+ - lib/libvirt/xml/disk.rb
86
+ - lib/libvirt/xml/domain.rb
87
+ - lib/libvirt/xml/generic.rb
88
+ - lib/libvirt/xml/graphics.rb
89
+ - lib/libvirt/xml/max_vcpu.rb
90
+ - lib/libvirt/xml/memory.rb
91
+ - lib/libvirt/xml/storage_pool.rb
92
+ - lib/libvirt/xml/storage_volume.rb
93
+ - lib/libvirt/xml/vcpu.rb
59
94
  - lib/libvirt_ffi.rb
60
95
  - libvirt.gemspec
61
96
  - test_usage/support/libvirt_async.rb
62
97
  - test_usage/support/log_formatter.rb
98
+ - test_usage/test_domain.rb
63
99
  - test_usage/test_event_loop.rb
100
+ - test_usage/test_libvirtd_restart.rb
101
+ - test_usage/test_metadata.rb
102
+ - test_usage/test_screenshot.rb
103
+ - test_usage/test_storage.rb
64
104
  homepage: https://github.com/senid231/libvirt_ffi
65
105
  licenses:
66
106
  - MIT