libvirt_ffi 0.4.1 → 0.5.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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +78 -0
  3. data/Gemfile +7 -3
  4. data/Rakefile +6 -1
  5. data/bin/console +1 -0
  6. data/exe/libvirt +1 -0
  7. data/lib/libvirt/base_info.rb +34 -0
  8. data/lib/libvirt/connection.rb +98 -36
  9. data/lib/libvirt/domain.rb +105 -8
  10. data/lib/libvirt/domain_callback_storage.rb +13 -15
  11. data/lib/libvirt/errors.rb +65 -0
  12. data/lib/libvirt/event.rb +29 -19
  13. data/lib/libvirt/ffi/common.rb +8 -1
  14. data/lib/libvirt/ffi/domain.rb +529 -196
  15. data/lib/libvirt/ffi/error.rb +243 -0
  16. data/lib/libvirt/ffi/event.rb +30 -36
  17. data/lib/libvirt/ffi/helpers.rb +17 -0
  18. data/lib/libvirt/ffi/host.rb +122 -0
  19. data/lib/libvirt/ffi/storage.rb +149 -0
  20. data/lib/libvirt/ffi/stream.rb +19 -17
  21. data/lib/libvirt/ffi.rb +17 -0
  22. data/lib/libvirt/node_info.rb +2 -41
  23. data/lib/libvirt/storage_pool.rb +70 -0
  24. data/lib/libvirt/storage_pool_info.rb +7 -0
  25. data/lib/libvirt/storage_volume.rb +51 -0
  26. data/lib/libvirt/storage_volume_info.rb +7 -0
  27. data/lib/libvirt/stream.rb +21 -14
  28. data/lib/libvirt/util.rb +61 -8
  29. data/lib/libvirt/version.rb +1 -1
  30. data/lib/libvirt/xml/disk.rb +59 -0
  31. data/lib/libvirt/xml/domain.rb +76 -0
  32. data/lib/libvirt/xml/generic.rb +252 -0
  33. data/lib/libvirt/xml/graphics.rb +14 -0
  34. data/lib/libvirt/xml/max_vcpu.rb +12 -0
  35. data/lib/libvirt/xml/memory.rb +14 -0
  36. data/lib/libvirt/xml/storage_pool.rb +24 -0
  37. data/lib/libvirt/xml/storage_volume.rb +32 -0
  38. data/lib/libvirt/xml/vcpu.rb +12 -0
  39. data/lib/libvirt/xml.rb +23 -0
  40. data/lib/libvirt.rb +12 -12
  41. data/lib/libvirt_ffi.rb +2 -0
  42. data/libvirt.gemspec +5 -1
  43. data/test_usage/support/libvirt_async.rb +27 -35
  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 +115 -39
  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 +14 -13
  50. data/test_usage/test_storage.rb +52 -0
  51. metadata +42 -6
  52. data/lib/libvirt/error.rb +0 -6
  53. data/lib/libvirt/ffi/connection.rb +0 -94
  54. data/lib/libvirt/ffi/libvirt.rb +0 -17
  55. data/lib/libvirt/ffi/node_info.rb +0 -37
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Libvirt
4
+ module Errors
5
+ class Error < StandardError
6
+ # Generic error
7
+ end
8
+
9
+ class LibError < Error
10
+ # Object contains detailed error information retrieved from libvirt.
11
+
12
+ ERROR_FIELDS = [:code, :domain, :message, :level].freeze
13
+
14
+ attr_reader :client_message,
15
+ :error_data,
16
+ :error_code,
17
+ :error_domain,
18
+ :error_message,
19
+ :error_level
20
+
21
+ # @param client_message [String, nil] optional client message
22
+ # When client_message ommited and virGetLastError return error
23
+ # message will be following: "ERROR_LEVEL: ERROR_NUMBER (ERROR_DOMAIN) ERROR_MESSAGE".
24
+ # When client message provided and virGetLastError return error
25
+ # message will be following: "CLIENT_MESSAGE\nERROR_LEVEL: ERROR_NUMBER (ERROR_DOMAIN) ERROR_MESSAGE".
26
+ # When client message is provided and virGetLastError return no error
27
+ # message will be following: "CLIENT_MESSAGE".
28
+ def initialize(client_message = nil)
29
+ @client_message = client_message
30
+ ptr = FFI::Error.virGetLastError
31
+ unless ptr.null?
32
+ struct = FFI::Error::Struct.new(ptr)
33
+ @error_data = struct.members.map { |m| [m, struct[m]] }.to_h
34
+ @error_code = error_data[:code]
35
+ @error_domain = error_data[:domain]
36
+ @error_message = error_data[:message]
37
+ @error_level = error_data[:level]
38
+ end
39
+
40
+ super(build_message)
41
+ end
42
+
43
+ private
44
+
45
+ def build_message
46
+ if error_data.nil?
47
+ client_message
48
+ elsif client_message.nil?
49
+ format '%<level>s: %<code>s (%<domain>s) %<message>s',
50
+ level: error_level,
51
+ code: error_code,
52
+ domain: error_domain,
53
+ message: error_message
54
+ else
55
+ format "%<client_message>s\n%<level>s: %<code>s (%<domain>s) %<message>s",
56
+ client_message: client_message,
57
+ level: error_level,
58
+ code: error_code,
59
+ domain: error_domain,
60
+ message: error_message
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
data/lib/libvirt/event.rb CHANGED
@@ -21,7 +21,7 @@ module Libvirt
21
21
 
22
22
  attr_accessor :debug
23
23
 
24
- Opaque = Struct.new(:cb, :opaque, :ff)
24
+ Opaque = Struct.new(:cb, :opaque, :free_func)
25
25
 
26
26
  def invoke_handle_callback(watch, fd, events, opaque)
27
27
  cb = opaque.cb
@@ -59,20 +59,25 @@ module Libvirt
59
59
  true
60
60
  end
61
61
 
62
- def register(add_handle:, update_handle:, remove_handle:, add_timer:, update_timer:, remove_timer:)
62
+ def schedule_operation(&block)
63
+ @schedule.call(&block)
64
+ end
65
+
66
+ def register(add_handle:, update_handle:, remove_handle:, add_timer:, update_timer:, remove_timer:, schedule:) # rubocop:disable Metrics/ParameterLists
63
67
  @add_handle = add_handle
64
68
  @update_handle = update_handle
65
69
  @remove_handle = remove_handle
66
70
  @add_timer = add_timer
67
71
  @update_timer = update_timer
68
72
  @remove_timer = remove_timer
73
+ @schedule = schedule
69
74
 
70
- @add_handle_cb = FFI::Event.event_add_handle_func(&method(:_add_handle).to_proc)
71
- @update_handle_cb = ::FFI::Function.new(:void, [:int, :int], &method(:_update_handle).to_proc)
72
- @remove_handle_cb = ::FFI::Function.new(:int, [:int], &method(:_remove_handle).to_proc)
73
- @add_timer_cb = FFI::Event.event_add_timeout_func(&method(:_add_timer).to_proc)
74
- @update_timer_cb = ::FFI::Function.new(:void, [:int, :int], &method(:_update_timer).to_proc)
75
- @remove_timer_cb = ::FFI::Function.new(:int, [:int], &method(:_remove_timer).to_proc)
75
+ @add_handle_cb = FFI::Event.callback_function(:virEventAddHandleFunc, &method(:_add_handle))
76
+ @update_handle_cb = FFI::Event.callback_function(:virEventUpdateHandleFunc, &method(:_update_handle))
77
+ @remove_handle_cb = FFI::Event.callback_function(:virEventRemoveHandleFunc, &method(:_remove_handle))
78
+ @add_timer_cb = FFI::Event.callback_function(:virEventAddTimeoutFunc, &method(:_add_timer))
79
+ @update_timer_cb = FFI::Event.callback_function(:virEventUpdateTimeoutFunc, &method(:_update_timer))
80
+ @remove_timer_cb = FFI::Event.callback_function(:virEventRemoveTimeoutFunc, &method(:_remove_timer))
76
81
 
77
82
  FFI::Event.virEventRegisterImpl(
78
83
  @add_handle_cb,
@@ -87,9 +92,9 @@ module Libvirt
87
92
 
88
93
  private
89
94
 
90
- def _add_handle(fd, event, cb, opaque, ff)
91
- dbg { "ADD_HANDLE fd=#{fd}, #{event}=event, cb=#{cb}, opaque=#{opaque}, ff=#{ff}" }
92
- op = Opaque.new(cb, opaque, ff)
95
+ def _add_handle(fd, event, cb, opaque, free_func)
96
+ dbg { "ADD_HANDLE fd=#{fd}, #{event}=event, cb=#{cb}, opaque=#{opaque}, free_func=#{free_func}" }
97
+ op = Opaque.new(cb, opaque, free_func)
93
98
  @add_handle.call(fd, event, op)
94
99
  end
95
100
 
@@ -101,15 +106,18 @@ module Libvirt
101
106
  def _remove_handle(watch)
102
107
  dbg { "REMOVE_HANDLE watch=#{watch}" }
103
108
  op = @remove_handle.call(watch)
104
- free_func = op.ff
109
+ free_func = op.free_func
105
110
  opaque = op.opaque
106
- free_func.call(opaque) unless free_func.null?
111
+ schedule_operation do
112
+ dbg { "REMOVE_HANDLE delayed free_func watch=#{watch}" }
113
+ free_func.call(opaque) unless free_func.null?
114
+ end
107
115
  0
108
116
  end
109
117
 
110
- def _add_timer(timeout, cb, opaque, ff)
111
- dbg { "ADD_TIMER timeout=#{timeout}, cb=#{cb}, opaque=#{opaque}, ff=#{ff}" }
112
- op = Opaque.new(cb, opaque, ff)
118
+ def _add_timer(timeout, cb, opaque, free_func)
119
+ dbg { "ADD_TIMER timeout=#{timeout}, cb=#{cb}, opaque=#{opaque}, free_func=#{free_func}" }
120
+ op = Opaque.new(cb, opaque, free_func)
113
121
  @add_timer.call(timeout, op)
114
122
  end
115
123
 
@@ -121,15 +129,17 @@ module Libvirt
121
129
  def _remove_timer(timer)
122
130
  dbg { "REMOVE_TIMER timer=#{timer}" }
123
131
  op = @remove_timer.call(timer)
124
- free_func = op.ff
132
+ free_func = op.free_func
125
133
  opaque = op.opaque
126
- free_func.call(opaque) unless free_func.null?
134
+ schedule_operation do
135
+ dbg { "REMOVE_TIMER async free_func timer=#{timer}" }
136
+ free_func.call(opaque) unless free_func.null?
137
+ end
127
138
  0
128
139
  end
129
140
 
130
141
  def dbg(&block)
131
142
  Util.log(:debug, 'Libvirt::Event', &block)
132
143
  end
133
-
134
144
  end
135
145
  end
@@ -3,13 +3,20 @@
3
3
  module Libvirt
4
4
  module FFI
5
5
  module Common
6
+ # https://libvirt.org/html/libvirt-libvirt-common.html
7
+
6
8
  extend ::FFI::Library
9
+ extend Helpers
7
10
  ffi_lib Util.library_path
8
11
 
9
- # typedef void (*virFreeCallback) (
12
+ # typedef void (*virFreeCallback) (
10
13
  # void * opaque
11
14
  # )
12
15
  FREE_CALLBACK = callback :virFreeCallback, [:pointer], :void
16
+
17
+ def self.free_function(*args, &block)
18
+ callback_function(FREE_CALLBACK, *args, &block)
19
+ end
13
20
  end
14
21
  end
15
22
  end