libvirt_ffi 0.4.1 → 0.5.0

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 -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