libvirt_ffi 0.5.3 → 0.6.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.
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