libvirt_ffi 0.2.1 → 0.5.1

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