libvirt_ffi 0.5.3 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2a2337cfa3a044b561ab70fe277e7fafff9f39919c494edc64e0f24dabce256d
4
- data.tar.gz: a2dbb17ebb8eca45d0336293da344f1b6959f5afdbcee394d87ad5c103a9406a
3
+ metadata.gz: 43c4cf7b7fa510b96605a9f05e8f04680280459d48572085740a71f145ce1442
4
+ data.tar.gz: a3ca5f72fdeb7de0cc95b440f58c5b894970add2cb746c12e3191d12269dcc42
5
5
  SHA512:
6
- metadata.gz: 3e1354133c74a9fe27affc1414f2e8a466fd1c97664e3ed365736c7f3c574d9e7e1530bd15af5d229442437e33cfcf4f18d48b8e538af7e62a49975d92d7b591
7
- data.tar.gz: 57d42fe97ad18a5827710d63eec68d0681ec1282d97168a71f1ce27263cc69c8f0063c4374543bb8baf0ff707a587080f23530b0fbc1d7ce8f158a46f57f62a4
6
+ metadata.gz: f1b7448f8ebd67349c59a365d1b30072bf99d5f78ffc1b07c87f99a312365f4d42474e62886c71e797fd0deab4c6f726af6440d6c4bb350fb8a65ee751b68ed5
7
+ data.tar.gz: 24056f945020275a102517bd6f4fba560be15c0f4fea7725b9c4b9b6032a1e94695b1520094c4027bf4ea0e34291e00148efefbb60d114640980e6c69e9f6cae
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'ffi'
4
4
  require 'objspace'
5
- require 'libvirt/domain_callback_storage'
5
+ require 'libvirt/host_callback_storage'
6
6
  require 'libvirt/util'
7
7
  require 'libvirt/errors'
8
8
  require 'libvirt/ffi'
@@ -3,19 +3,45 @@
3
3
  module Libvirt
4
4
  class Connection
5
5
  DOMAIN_EVENT_IDS = FFI::Domain.enum_type(:event_id).symbols.dup.freeze
6
+ POOL_EVENT_IDS = FFI::Storage.enum_type(:event_id).symbols.dup.freeze
6
7
 
7
- STORAGE = DomainCallbackStorage.new
8
+ DOMAIN_STORAGE = HostCallbackStorage.new(:domain_event)
9
+ POOL_STORAGE = HostCallbackStorage.new(:storage_pool_event)
10
+ CLOSE_STORAGE = HostCallbackStorage.new(:close)
8
11
 
9
12
  DOMAIN_EVENT_CALLBACKS = DOMAIN_EVENT_IDS.map do |event_id_sym|
10
13
  func = FFI::Domain.event_callback_for(event_id_sym) do |conn_ptr, dom_ptr, *args, op_ptr|
14
+ Util.log(:debug, "DOMAIN_EVENT_CALLBACKS[#{event_id_sym}]") do
15
+ "inside callback conn_ptr=#{conn_ptr}, pool_ptr=#{dom_ptr}, args=#{args}, op_ptr=#{op_ptr}"
16
+ end
11
17
  connection = Connection.load_ref(conn_ptr)
12
18
  domain = Domain.load_ref(dom_ptr)
13
- block, opaque = STORAGE.retrieve_from_pointer(op_ptr)
19
+ block, opaque = DOMAIN_STORAGE.retrieve_from_pointer(op_ptr)
14
20
  block.call(connection, domain, *args, opaque)
15
21
  end
16
22
  [event_id_sym, func]
17
23
  end.to_h.freeze
18
24
 
25
+ POOL_EVENT_CALLBACKS = POOL_EVENT_IDS.map do |event_id_sym|
26
+ func = FFI::Storage.event_callback_for(event_id_sym) do |conn_ptr, pool_ptr, *args, op_ptr|
27
+ Util.log(:debug, "POOL_EVENT_CALLBACKS[#{event_id_sym}]") do
28
+ "inside callback conn_ptr=#{conn_ptr}, pool_ptr=#{pool_ptr}, args=#{args}, op_ptr=#{op_ptr}"
29
+ end
30
+ connection = Connection.load_ref(conn_ptr)
31
+ pool = StoragePool.load_ref(pool_ptr)
32
+ block, opaque = POOL_STORAGE.retrieve_from_pointer(op_ptr)
33
+ block.call(connection, pool, *args, opaque)
34
+ end
35
+ [event_id_sym, func]
36
+ end.to_h.freeze
37
+
38
+ CLOSE_CALLBACK = FFI::Host.callback_function(:virConnectCloseFunc) do |conn_ptr, reason, op_ptr|
39
+ Util.log(:debug, 'CLOSE_CALLBACK') { "inside callback conn_ptr=#{conn_ptr}, reason=#{reason}, op_ptr=#{op_ptr}" }
40
+ connection = Connection.load_ref(conn_ptr)
41
+ block, opaque = CLOSE_STORAGE.retrieve_from_pointer(op_ptr)
42
+ block.call(connection, reason, opaque)
43
+ end
44
+
19
45
  def self.load_ref(conn_ptr)
20
46
  ref_result = FFI::Host.virConnectRef(conn_ptr)
21
47
  raise Errors::LibError, "Couldn't retrieve connection reference" if ref_result.negative?
@@ -136,18 +162,27 @@ module Libvirt
136
162
 
137
163
  def register_close_callback(opaque = nil, &block)
138
164
  dbg { "#register_close_callback opaque=#{opaque}" }
139
- raise ArgumentError, 'close function already registered' if @close_data
140
165
 
141
- @close_data = { opaque: opaque, block: block }
142
- @close_cb = FFI::Host.callback_function(:virConnectCloseFunc) do |_conn, reason, _op|
143
- dbg { "CONNECTION CLOSED @conn_ptr=#{@conn_ptr} reason=#{reason}" }
144
- @close_data[:block].call(self, reason, @close_data[:opaque])
145
- end
146
- @close_free_func = FFI::Common.free_function do
147
- dbg { "CONNECTION CLOSED FREE FUNC @conn_ptr=#{@conn_ptr}" }
148
- @close_cb = @close_free_func = @close_data = nil
166
+ cb_data, cb_data_free_func = CLOSE_STORAGE.allocate_struct
167
+ result = FFI::Host.virConnectRegisterCloseCallback(
168
+ @conn_ptr,
169
+ CLOSE_CALLBACK,
170
+ cb_data.pointer,
171
+ cb_data_free_func
172
+ )
173
+ if result.negative?
174
+ cb_data.pointer.free
175
+ raise Errors::LibError, "Couldn't register connection close callback"
149
176
  end
150
- FFI::Host.virConnectRegisterCloseCallback(@conn_ptr, @close_cb, nil, @close_free_func)
177
+
178
+ CLOSE_STORAGE.store_struct(
179
+ cb_data,
180
+ connection_pointer: @conn_ptr,
181
+ callback_id: result,
182
+ cb: block,
183
+ opaque: opaque
184
+ )
185
+ result
151
186
  end
152
187
 
153
188
  # @yield conn, dom, *args
@@ -158,7 +193,7 @@ module Libvirt
158
193
  event_id, event_id_sym = Util.parse_enum(enum, event_id)
159
194
  cb = DOMAIN_EVENT_CALLBACKS.fetch(event_id_sym)
160
195
 
161
- cb_data, cb_data_free_func = STORAGE.allocate_struct
196
+ cb_data, cb_data_free_func = DOMAIN_STORAGE.allocate_struct
162
197
 
163
198
  result = FFI::Domain.virConnectDomainEventRegisterAny(
164
199
  @conn_ptr,
@@ -173,7 +208,7 @@ module Libvirt
173
208
  raise Errors::LibError, "Couldn't register domain event callback"
174
209
  end
175
210
 
176
- STORAGE.store_struct(
211
+ DOMAIN_STORAGE.store_struct(
177
212
  cb_data,
178
213
  connection_pointer: @conn_ptr,
179
214
  callback_id: result,
@@ -190,7 +225,61 @@ module Libvirt
190
225
  raise Errors::LibError, "Couldn't deregister domain event callback" if result.negative?
191
226
 
192
227
  # virConnectDomainEventDeregisterAny will call free func
193
- # So we don't need to remove object from STORAGE here.
228
+ # So we don't need to remove object from DOMAIN_STORAGE here.
229
+ true
230
+ end
231
+
232
+ def register_storage_pool_event_callback(event_id, storage_pool = nil, opaque = nil, &block)
233
+ dbg { "#register_storage_pool_event_callback event_id=#{event_id}" }
234
+
235
+ enum = FFI::Storage.enum_type(:event_id)
236
+ event_id, event_id_sym = Util.parse_enum(enum, event_id)
237
+ cb = POOL_EVENT_CALLBACKS.fetch(event_id_sym)
238
+
239
+ cb_data, cb_data_free_func = POOL_STORAGE.allocate_struct
240
+
241
+ result = FFI::Storage.virConnectStoragePoolEventRegisterAny(
242
+ @conn_ptr,
243
+ storage_pool&.to_ptr,
244
+ event_id,
245
+ cb,
246
+ cb_data.pointer,
247
+ cb_data_free_func
248
+ )
249
+ if result.negative?
250
+ cb_data.pointer.free
251
+ raise Errors::LibError, "Couldn't register storage pool event callback"
252
+ end
253
+
254
+ POOL_STORAGE.store_struct(
255
+ cb_data,
256
+ connection_pointer: @conn_ptr,
257
+ callback_id: result,
258
+ cb: block,
259
+ opaque: opaque
260
+ )
261
+ result
262
+ end
263
+
264
+ def deregister_storage_pool_event_callback(callback_id)
265
+ dbg { "#deregister_storage_pool_event_callback callback_id=#{callback_id}" }
266
+
267
+ result = FFI::Storage.virConnectStoragePoolEventDeregisterAny(@conn_ptr, callback_id)
268
+ raise Errors::LibError, "Couldn't deregister storage pool event callback" if result.negative?
269
+
270
+ # virConnectStoragePoolEventDeregisterAny will call free func
271
+ # So we don't need to remove object from POOL_STORAGE here.
272
+ true
273
+ end
274
+
275
+ def deregister_close_callback
276
+ dbg { '#deregister_close_callback' }
277
+
278
+ result = FFI::Host.virConnectUnregisterCloseCallback(@conn_ptr, CLOSE_CALLBACK)
279
+ raise Errors::LibError, "Couldn't deregister close callback" if result.negative?
280
+
281
+ # virConnectUnregisterCloseCallback will call free func
282
+ # So we don't need to remove object from CLOSE_STORAGE here.
194
283
  true
195
284
  end
196
285
 
@@ -38,7 +38,7 @@ module Libvirt
38
38
  end
39
39
 
40
40
  def uuid
41
- buff = ::FFI::MemoryPointer.new(:char, FFI::Domain::UUID_STRING_BUFLEN)
41
+ buff = ::FFI::MemoryPointer.new(:char, Util::UUID_STRING_BUFLEN)
42
42
  result = FFI::Domain.virDomainGetUUIDString(@dom_ptr, buff)
43
43
  raise Errors::LibError, "Couldn't get domain uuid" if result.negative?
44
44
 
@@ -46,7 +46,10 @@ module Libvirt
46
46
  end
47
47
 
48
48
  def name
49
- FFI::Domain.virDomainGetName(@dom_ptr)
49
+ result = FFI::Domain.virDomainGetName(@dom_ptr)
50
+ raise Errors::LibError, "Couldn't retrieve storage pool name" if result.nil?
51
+
52
+ result
50
53
  end
51
54
 
52
55
  def max_vcpus
@@ -179,6 +182,13 @@ module Libvirt
179
182
  result
180
183
  end
181
184
 
185
+ def persistent?
186
+ result = FFI::Domain.virDomainIsPersistent(@dom_ptr)
187
+ raise Errors::LibError, "Couldn't set domain metadata" if result.negative?
188
+
189
+ result == 1
190
+ end
191
+
182
192
  private
183
193
 
184
194
  def dbg(&block)
@@ -9,8 +9,6 @@ module Libvirt
9
9
  extend Helpers
10
10
  ffi_lib Util.library_path
11
11
 
12
- UUID_STRING_BUFLEN = 0x80 # RFC4122
13
-
14
12
  EVENT_ID_TO_CALLBACK = {
15
13
  LIFECYCLE: :virConnectDomainEventCallback,
16
14
  REBOOT: :virConnectDomainEventGenericCallback,
@@ -798,6 +796,11 @@ module Libvirt
798
796
  [:pointer, :metadata_type, :string, :modification_impact],
799
797
  :string
800
798
 
799
+ # int virDomainIsPersistent (
800
+ # virDomainPtr dom
801
+ # )
802
+ attach_function :virDomainIsPersistent, [:pointer], :int
803
+
801
804
  # Converts detail from lifecycle callback from integer to symbol name.
802
805
  # @param event [Symbol] enum :event_type (virDomainEventType)
803
806
  # @param detail [Integer]
@@ -807,6 +810,10 @@ module Libvirt
807
810
  detail_enum[detail]
808
811
  end
809
812
 
813
+ # Converts state reason of domain from integer to symbol name.
814
+ # @param state [Symbol] enum :state (virDomainState)
815
+ # @param reason [Integer]
816
+ # @return [Symbol]
810
817
  def self.state_reason(state, reason)
811
818
  reason_enum = enum_type(:"#{state.to_s.downcase}_reason")
812
819
  reason_enum[reason]
@@ -31,6 +31,14 @@ module Libvirt
31
31
  :threads, :uint
32
32
  end
33
33
 
34
+ # enum virConnectCloseReason
35
+ enum :close_reason, [
36
+ :ERROR, 0x0, # Misc I/O error
37
+ :EOF, 0x1, # End-of-file from server
38
+ :KEEPALIVE, 0x2, # Keepalive timer triggered
39
+ :CLIENT, 0x3 # Client requested it
40
+ ]
41
+
34
42
  # int virGetVersion (
35
43
  # unsigned long *libVer,
36
44
  # const char *type,
@@ -49,7 +57,7 @@ module Libvirt
49
57
  # int reason,
50
58
  # void * opaque
51
59
  # )
52
- callback :virConnectCloseFunc, [:pointer, :int, :pointer], :void
60
+ callback :virConnectCloseFunc, [:pointer, :close_reason, :pointer], :void
53
61
 
54
62
  # virConnectPtr virConnectOpen (const char * name)
55
63
  attach_function :virConnectOpen, [:string], :pointer
@@ -121,7 +129,7 @@ module Libvirt
121
129
  # unsigned long long virNodeGetFreeMemory (
122
130
  # virConnectPtr conn
123
131
  # )
124
- attach_function :virNodeGetFreeMemory, [:pointer], :u_long_long
132
+ attach_function :virNodeGetFreeMemory, [:pointer], :ulong_long
125
133
  end
126
134
  end
127
135
  end
@@ -9,6 +9,11 @@ module Libvirt
9
9
  extend Helpers
10
10
  ffi_lib Util.library_path
11
11
 
12
+ EVENT_ID_TO_CALLBACK = {
13
+ LIFECYCLE: :virConnectStoragePoolEventLifecycleCallback,
14
+ REFRESH: :virConnectStoragePoolEventGenericCallback
15
+ }.freeze
16
+
12
17
  # enum virStoragePoolState
13
18
  enum :pool_state, [
14
19
  :INACTIVE, 0x0, # Not running
@@ -63,6 +68,23 @@ module Libvirt
63
68
  :INACTIVE, 0x1 # dump inactive pool/volume information
64
69
  ]
65
70
 
71
+ # enum virStoragePoolEventID
72
+ enum :event_id, [
73
+ :LIFECYCLE, 0x0, # virConnectStoragePoolEventLifecycleCallback
74
+ :REFRESH, 0x1 # virConnectStoragePoolEventGenericCallback
75
+ ]
76
+
77
+ # enum virStoragePoolEventLifecycleType
78
+ enum :event_lifecycle_type, [
79
+ :DEFINED, 0x0,
80
+ :UNDEFINED, 0x1,
81
+ :STARTED, 0x2,
82
+ :STOPPED, 0x3,
83
+ :CREATED, 0x4,
84
+ :DELETED, 0x5,
85
+ :LAST, 0x6
86
+ ]
87
+
66
88
  # struct virStoragePoolInfo {
67
89
  # int state # virStoragePoolState flags
68
90
  # unsigned long long capacity # Logical size bytes
@@ -87,6 +109,26 @@ module Libvirt
87
109
  :allocation, :ulong_long
88
110
  end
89
111
 
112
+ # typedef void (*virConnectStoragePoolEventGenericCallback) (
113
+ # virConnectPtr conn,
114
+ # virStoragePoolPtr pool,
115
+ # void * opaque
116
+ # )
117
+ callback :virConnectStoragePoolEventGenericCallback,
118
+ [:pointer, :pointer, :pointer],
119
+ :void
120
+
121
+ # typedef void (*virConnectStoragePoolEventLifecycleCallback) (
122
+ # virConnectPtr conn,
123
+ # virStoragePoolPtr pool,
124
+ # int event,
125
+ # int detail,
126
+ # void * opaque
127
+ # )
128
+ callback :virConnectStoragePoolEventLifecycleCallback,
129
+ [:pointer, :pointer, :event_lifecycle_type, :int, :pointer],
130
+ :void
131
+
90
132
  # int virConnectListAllStoragePools (
91
133
  # virConnectPtr conn,
92
134
  # virStoragePoolPtr ** pools,
@@ -144,6 +186,49 @@ module Libvirt
144
186
  # unsigned int flags
145
187
  # )
146
188
  attach_function :virStorageVolGetXMLDesc, [:pointer, :xml_flags], :string
189
+
190
+ # int virConnectStoragePoolEventRegisterAny (
191
+ # virConnectPtr conn,
192
+ # virStoragePoolPtr pool,
193
+ # int eventID,
194
+ # virConnectStoragePoolEventGenericCallback cb,
195
+ # void * opaque,
196
+ # virFreeCallback freecb
197
+ # )
198
+ attach_function :virConnectStoragePoolEventRegisterAny,
199
+ [:pointer, :pointer, :event_id, :pointer, :pointer, FFI::Common::FREE_CALLBACK],
200
+ :int
201
+
202
+ # int virConnectStoragePoolEventDeregisterAny (
203
+ # virConnectPtr conn,
204
+ # int callbackID
205
+ # )
206
+ attach_function :virConnectStoragePoolEventDeregisterAny,
207
+ [:pointer, :int],
208
+ :int
209
+
210
+ # int virStoragePoolGetUUIDString (virStoragePoolPtr pool,
211
+ # char * buf)
212
+ attach_function :virStoragePoolGetUUIDString, [:pointer, :pointer], :int
213
+
214
+ # const char * virStoragePoolGetName (virStoragePoolPtr pool)
215
+ attach_function :virStoragePoolGetName, [:pointer], :string
216
+
217
+ module_function
218
+
219
+ # Creates event callback function for provided event_id
220
+ # @param event_id [Integer,Symbol]
221
+ # @yield connect_ptr, domain_ptr, *args, opaque_ptr
222
+ # @return [FFI::Function]
223
+ def event_callback_for(event_id, &block)
224
+ event_id_sym = event_id.is_a?(Symbol) ? event_id : enum_type(:event_id)[event_id]
225
+
226
+ callback_name = EVENT_ID_TO_CALLBACK.fetch(event_id_sym)
227
+ callback_function(callback_name) do |*args|
228
+ Util.log(:debug, name) { ".event_callback_for #{event_id_sym} CALLBACK #{args.map(&:to_s).join(', ')}," }
229
+ block.call(*args)
230
+ end
231
+ end
147
232
  end
148
233
  end
149
234
  end
@@ -1,18 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Libvirt
4
- class DomainCallbackStorage
4
+ class HostCallbackStorage
5
5
  class CallbackDataStruct < ::FFI::Struct
6
6
  layout :connection_pointer, :pointer,
7
7
  :callback_id, :int
8
8
  end
9
9
 
10
- def initialize
10
+ attr_reader :name
11
+
12
+ def initialize(name)
13
+ @name = name
11
14
  @inner_storage = Hash.new { |h, key| h[key] = {} }
12
15
  end
13
16
 
14
17
  # @return [Array<2>]
15
- # cb_data [Libvirt::DomainCallbackStorage::CallbackDataStruct],
18
+ # cb_data [Libvirt::HostCallbackStorage::CallbackDataStruct],
16
19
  # cb_data_free_func [FFI::Function]
17
20
  def allocate_struct
18
21
  dbg { '#allocate_struct' }
@@ -20,7 +23,7 @@ module Libvirt
20
23
  cb_data_ptr = ::FFI::MemoryPointer.new(:char, CallbackDataStruct.size, false)
21
24
  cb_data = CallbackDataStruct.new(cb_data_ptr)
22
25
  cb_data_free_func = FFI::Common.free_function do |pointer|
23
- dbg { 'Libvirt::DomainCallbackStorage cb_data_free_func triggered' }
26
+ dbg { "cb_data_free_func triggered pointer=#{pointer}" }
24
27
  remove_struct(pointer)
25
28
  end
26
29
  [cb_data, cb_data_free_func]
@@ -35,7 +38,7 @@ module Libvirt
35
38
  end
36
39
 
37
40
  def remove_struct(pointer)
38
- dbg { "#remove_struct pointer=#{pointer}" }
41
+ dbg { "#remove_struct pointer=#{pointer}," }
39
42
 
40
43
  cb_data_struct = CallbackDataStruct.new(pointer)
41
44
  connection_pointer = cb_data_struct[:connection_pointer]
@@ -63,7 +66,7 @@ module Libvirt
63
66
  private
64
67
 
65
68
  def dbg(&block)
66
- Util.log(:debug, 'Libvirt::DomainCallbackStorage', &block)
69
+ Util.log(:debug, "Libvirt::HostCallbackStorage(#{name})", &block)
67
70
  end
68
71
  end
69
72
  end
@@ -61,6 +61,21 @@ module Libvirt
61
61
  ptr.get_array_of_pointer(0, size).map { |stv_ptr| StorageVolume.new(stv_ptr) }
62
62
  end
63
63
 
64
+ def uuid
65
+ buff = ::FFI::MemoryPointer.new(:char, Util::UUID_STRING_BUFLEN)
66
+ result = FFI::Storage.virStoragePoolGetUUIDString(@ptr, buff)
67
+ raise Errors::LibError, "Couldn't get storage pool uuid" if result.negative?
68
+
69
+ buff.read_string
70
+ end
71
+
72
+ def name
73
+ result = FFI::Storage.virStoragePoolGetName(@ptr)
74
+ raise Errors::LibError, "Couldn't retrieve storage pool name" if result.nil?
75
+
76
+ result
77
+ end
78
+
64
79
  private
65
80
 
66
81
  def dbg(&block)
@@ -19,6 +19,8 @@ module Libvirt
19
19
  TiB: 1_099_511_627_776
20
20
  }.freeze
21
21
 
22
+ UUID_STRING_BUFLEN = 0x80 # RFC4122
23
+
22
24
  class << self
23
25
  attr_writer :logger
24
26
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Libvirt
4
- VERSION = '0.5.3'
4
+ VERSION = '0.6.1'
5
5
  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.5.3
4
+ version: 0.6.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-03-23 00:00:00.000000000 Z
11
+ date: 2020-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -61,7 +61,6 @@ files:
61
61
  - lib/libvirt/base_info.rb
62
62
  - lib/libvirt/connection.rb
63
63
  - lib/libvirt/domain.rb
64
- - lib/libvirt/domain_callback_storage.rb
65
64
  - lib/libvirt/errors.rb
66
65
  - lib/libvirt/event.rb
67
66
  - lib/libvirt/ffi.rb
@@ -73,6 +72,7 @@ files:
73
72
  - lib/libvirt/ffi/host.rb
74
73
  - lib/libvirt/ffi/storage.rb
75
74
  - lib/libvirt/ffi/stream.rb
75
+ - lib/libvirt/host_callback_storage.rb
76
76
  - lib/libvirt/node_info.rb
77
77
  - lib/libvirt/storage_pool.rb
78
78
  - lib/libvirt/storage_pool_info.rb