libvirt_ffi 0.6.1 → 0.8.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: 43c4cf7b7fa510b96605a9f05e8f04680280459d48572085740a71f145ce1442
4
- data.tar.gz: a3ca5f72fdeb7de0cc95b440f58c5b894970add2cb746c12e3191d12269dcc42
3
+ metadata.gz: d81d03c71f0077138bdc7369c7468138333eb45ae1de85c857089b263975e8c4
4
+ data.tar.gz: cdae17b6ecb8174ee12247d31d4419a9bf367ba17a460c6f9e3e5cc347d313ca
5
5
  SHA512:
6
- metadata.gz: f1b7448f8ebd67349c59a365d1b30072bf99d5f78ffc1b07c87f99a312365f4d42474e62886c71e797fd0deab4c6f726af6440d6c4bb350fb8a65ee751b68ed5
7
- data.tar.gz: 24056f945020275a102517bd6f4fba560be15c0f4fea7725b9c4b9b6032a1e94695b1520094c4027bf4ea0e34291e00148efefbb60d114640980e6c69e9f6cae
6
+ metadata.gz: 4f2a8d886ed935f536bd5e04fd9e710d953d0f7f78a8e408220018784291ac3ba71f2e342dcaedbe44b3b57c2e1c77cd36784a05f9d6a0b486ddc6b1dfeb1bd3
7
+ data.tar.gz: 3df70b41610251d35c2986ba77fd617ee15cb956dc690f850b4650ac34ef4fee80072987d83b1cefcf806501fd87e6401def2c2d2d120e5d8db1b09136d21742
@@ -0,0 +1,26 @@
1
+ name: Tests
2
+ on:
3
+ pull_request:
4
+ push:
5
+ branches:
6
+ - master
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ ruby: [ '2.6', '2.7', '3.0' ]
14
+ name: Tests with Ruby ${{ matrix.ruby }}
15
+ steps:
16
+ - name: Install libvirt
17
+ run: sudo apt-get install -y libvirt-dev libvirt0
18
+ - uses: actions/checkout@v2
19
+ - uses: actions/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{ matrix.ruby }}
22
+ - name: Run tests
23
+ run: |
24
+ gem install bundler
25
+ bundle install
26
+ bundle exec rake
data/.gitignore CHANGED
@@ -6,5 +6,6 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
-
10
9
  /Gemfile.lock
10
+ .rspec_local
11
+ /spec/last_run.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml CHANGED
@@ -5,7 +5,7 @@ AllCops:
5
5
  - vendor/**/*
6
6
  - tmp/**/*
7
7
  - pkg/*
8
- - test_usage/**/*.rb
8
+ - examples/**/*.rb
9
9
 
10
10
  Layout/LineLength:
11
11
  Max: 180
data/Gemfile CHANGED
@@ -5,14 +5,11 @@ source 'https://rubygems.org'
5
5
  # Specify your gem's dependencies in libvirt.gemspec
6
6
  gemspec
7
7
 
8
- gem 'minitest', '~> 5.0'
9
- gem 'rake', '~> 12.0'
10
-
8
+ gem 'activesupport'
9
+ gem 'async', '~> 1.24'
10
+ gem 'gc_tracer'
11
+ gem 'get_process_mem'
11
12
  gem 'nokogiri'
12
-
13
- group :development do
14
- gem 'activesupport'
15
- gem 'async', '~> 1.24'
16
- gem 'gc_tracer'
17
- gem 'get_process_mem'
18
- end
13
+ gem 'rake', '~> 12.0'
14
+ gem 'rspec', '~> 3.9'
15
+ gem 'rubocop', '~> 0.80.1'
data/README.md CHANGED
@@ -32,7 +32,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
32
 
33
33
  ## Contributing
34
34
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/libvirt. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/libvirt/blob/master/CODE_OF_CONDUCT.md).
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/senid231/libvirt. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/senid231/libvirt/blob/master/CODE_OF_CONDUCT.md).
36
36
 
37
37
 
38
38
  ## License
@@ -41,4 +41,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
41
41
 
42
42
  ## Code of Conduct
43
43
 
44
- Everyone interacting in the Libvirt project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/libvirt/blob/master/CODE_OF_CONDUCT.md).
44
+ Everyone interacting in the Libvirt project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/senid231/libvirt/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile CHANGED
@@ -1,15 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/gem_tasks'
4
- require 'rake/testtask'
4
+ require 'rspec/core/rake_task'
5
5
  require 'rubocop/rake_task'
6
6
 
7
- Rake::TestTask.new(:test) do |t|
8
- t.libs << 'test'
9
- t.libs << 'lib'
10
- t.test_files = FileList['test/**/*_test.rb']
11
- end
12
-
7
+ RSpec::Core::RakeTask.new(:spec)
13
8
  RuboCop::RakeTask.new(:rubocop)
14
9
 
15
- task default: [:rubocop, :test]
10
+ task default: [:rubocop, :spec]
@@ -16,6 +16,7 @@ module Libvirt
16
16
  end
17
17
  end
18
18
 
19
+ # @param pointer [FFI::Pointer]
19
20
  def initialize(pointer)
20
21
  raise ArgumentError, "Can't initialize base class #{self.class}" if self.class == BaseInfo
21
22
 
@@ -23,12 +24,19 @@ module Libvirt
23
24
  @struct = self.class._struct_class.new(pointer)
24
25
  end
25
26
 
27
+ # @param attr [Symbol]
28
+ # @return [Object, nil]
26
29
  def [](attr)
27
30
  @struct[attr]
28
31
  end
29
32
 
33
+ # @return [Hash]
30
34
  def to_h
31
35
  @struct.members.map { |attr| [attr, @struct[attr]] }.to_h
32
36
  end
37
+
38
+ def to_ptr
39
+ @struct.to_ptr
40
+ end
33
41
  end
34
42
  end
@@ -2,11 +2,15 @@
2
2
 
3
3
  module Libvirt
4
4
  class Connection
5
+ include Loggable
6
+
5
7
  DOMAIN_EVENT_IDS = FFI::Domain.enum_type(:event_id).symbols.dup.freeze
6
8
  POOL_EVENT_IDS = FFI::Storage.enum_type(:event_id).symbols.dup.freeze
9
+ NETWORK_EVENT_IDS = FFI::Network.enum_type(:event_id).symbols.dup.freeze
7
10
 
8
11
  DOMAIN_STORAGE = HostCallbackStorage.new(:domain_event)
9
12
  POOL_STORAGE = HostCallbackStorage.new(:storage_pool_event)
13
+ NETWORK_STORAGE = HostCallbackStorage.new(:network_event)
10
14
  CLOSE_STORAGE = HostCallbackStorage.new(:close)
11
15
 
12
16
  DOMAIN_EVENT_CALLBACKS = DOMAIN_EVENT_IDS.map do |event_id_sym|
@@ -35,6 +39,19 @@ module Libvirt
35
39
  [event_id_sym, func]
36
40
  end.to_h.freeze
37
41
 
42
+ NETWORK_EVENT_CALLBACKS = NETWORK_EVENT_IDS.map do |event_id_sym|
43
+ func = FFI::Network.event_callback_for(event_id_sym) do |conn_ptr, pool_ptr, *args, op_ptr|
44
+ Util.log(:debug, "NETWORK_EVENT_CALLBACKS[#{event_id_sym}]") do
45
+ "inside callback conn_ptr=#{conn_ptr}, pool_ptr=#{pool_ptr}, args=#{args}, op_ptr=#{op_ptr}"
46
+ end
47
+ connection = Connection.load_ref(conn_ptr)
48
+ pool = Network.load_ref(pool_ptr)
49
+ block, opaque = NETWORK_STORAGE.retrieve_from_pointer(op_ptr)
50
+ block.call(connection, pool, *args, opaque)
51
+ end
52
+ [event_id_sym, func]
53
+ end.to_h.freeze
54
+
38
55
  CLOSE_CALLBACK = FFI::Host.callback_function(:virConnectCloseFunc) do |conn_ptr, reason, op_ptr|
39
56
  Util.log(:debug, 'CLOSE_CALLBACK') { "inside callback conn_ptr=#{conn_ptr}, reason=#{reason}, op_ptr=#{op_ptr}" }
40
57
  connection = Connection.load_ref(conn_ptr)
@@ -42,56 +59,68 @@ module Libvirt
42
59
  block.call(connection, reason, opaque)
43
60
  end
44
61
 
45
- def self.load_ref(conn_ptr)
46
- ref_result = FFI::Host.virConnectRef(conn_ptr)
47
- raise Errors::LibError, "Couldn't retrieve connection reference" if ref_result.negative?
62
+ def self.load_ref(ptr)
63
+ result = FFI::Host.virConnectRef(ptr)
64
+ raise Errors::LibError, "Couldn't retrieve connection reference" if result.negative?
48
65
 
49
- new(nil).tap { |r| r.send(:set_connection, conn_ptr) }
66
+ uri = FFI::Host.virConnectGetURI(ptr)
67
+ new(uri).tap { |c| c.instance_variable_set(:@ptr, ptr) }
50
68
  end
51
69
 
70
+ attr_reader :uri
71
+
52
72
  def initialize(uri)
53
73
  @uri = uri
54
- @conn_ptr = ::FFI::Pointer.new(0)
74
+ @ptr = ::FFI::Pointer.new(0)
55
75
  @close_data = nil
56
76
 
57
- free = ->(obj_id) do
58
- Util.log(:debug) { "Finalize Libvirt::Connection 0x#{obj_id.to_s(16)} @conn_ptr=#{@conn_ptr}," }
59
- return if @conn_ptr.null?
77
+ Util.define_finalizer(self) { |pointer| FFI::Host.virConnectClose(pointer) }
78
+ end
60
79
 
61
- cl_result = FFI::Host.virConnectClose(@conn_ptr)
62
- warn "Couldn't close Libvirt::Connection (0x#{obj_id.to_s(16)}) pointer #{@conn_ptr.address}" if cl_result.negative?
63
- end
64
- ObjectSpace.define_finalizer(self, free)
80
+ def to_s
81
+ "#<#{self.class}:0x#{object_id.to_s(16)} @uri=#{@uri.inspect} @ptr=0x#{@ptr.address.to_s(16)}>"
82
+ end
83
+
84
+ def inspect
85
+ to_s
86
+ end
87
+
88
+ def to_ptr
89
+ @ptr
65
90
  end
66
91
 
67
92
  def open
68
- @conn_ptr = FFI::Host.virConnectOpen(@uri)
69
- raise Errors::LibError, "Couldn't open connection to #{@uri.inspect}" if @conn_ptr.null?
93
+ @ptr = FFI::Host.virConnectOpen(@uri)
94
+ raise Errors::LibError, "Couldn't open connection to #{@uri.inspect}" if @ptr.null?
95
+
96
+ dbg { 'opened' }
70
97
 
71
98
  true
72
99
  end
73
100
 
74
101
  def close
75
- result = FFI::Host.virConnectClose(@conn_ptr)
102
+ result = FFI::Host.virConnectClose(@ptr)
76
103
  raise Errors::LibError, "Couldn't close connection to #{@uri.inspect}" if result.negative?
77
104
 
78
- @conn_ptr = ::FFI::Pointer.new(0)
105
+ dbg { 'closed' }
106
+
107
+ @ptr = ::FFI::Pointer.new(0)
79
108
  true
80
109
  end
81
110
 
82
111
  def opened?
83
- !@conn_ptr.null?
112
+ !@ptr.null?
84
113
  end
85
114
 
86
- def to_ptr
87
- @conn_ptr
115
+ def closed?
116
+ !opened?
88
117
  end
89
118
 
90
119
  def version
91
120
  check_open!
92
121
 
93
122
  version_ptr = ::FFI::MemoryPointer.new(:ulong)
94
- result = FFI::Host.virConnectGetVersion(@conn_ptr, version_ptr)
123
+ result = FFI::Host.virConnectGetVersion(@ptr, version_ptr)
95
124
  raise Errors::LibError, "Couldn't retrieve connection version" if result.negative?
96
125
 
97
126
  version_number = version_ptr.get_ulong(0)
@@ -99,29 +128,21 @@ module Libvirt
99
128
  end
100
129
 
101
130
  def set_keep_alive(interval, count)
102
- result = FFI::Host.virConnectSetKeepAlive(@conn_ptr, interval, count)
131
+ result = FFI::Host.virConnectSetKeepAlive(@ptr, interval, count)
103
132
  raise Errors::LibError, "Couldn't set connection keep_alive" if result.negative?
104
133
 
105
134
  result.zero?
106
135
  end
107
136
 
108
137
  def free_memory
109
- result = FFI::Host.virNodeGetFreeMemory(@conn_ptr)
138
+ result = FFI::Host.virNodeGetFreeMemory(@ptr)
110
139
  raise Errors::LibError, "Couldn't set connection keep_alive" if result.negative?
111
140
 
112
141
  result
113
142
  end
114
143
 
115
- def to_s
116
- "#<#{self.class}:0x#{object_id.to_s(16)} @uri=#{@uri.inspect} @conn_ptr=0x#{@conn_ptr.address.to_s(16)}>"
117
- end
118
-
119
- def inspect
120
- to_s
121
- end
122
-
123
144
  def list_all_domains_qty(flags = 0)
124
- result = FFI::Domain.virConnectListAllDomains(@conn_ptr, nil, flags)
145
+ result = FFI::Domain.virConnectListAllDomains(@ptr, nil, flags)
125
146
  raise Errors::LibError, "Couldn't retrieve domains qty with flags #{flags.to_s(16)}" if result.negative?
126
147
 
127
148
  result
@@ -132,7 +153,7 @@ module Libvirt
132
153
  return [] if size.zero?
133
154
 
134
155
  domains_ptr = ::FFI::MemoryPointer.new(:pointer, size)
135
- result = FFI::Domain.virConnectListAllDomains(@conn_ptr, domains_ptr, flags)
156
+ result = FFI::Domain.virConnectListAllDomains(@ptr, domains_ptr, flags)
136
157
  raise Errors::LibError, "Couldn't retrieve domains list with flags #{flags.to_s(16)}" if result.negative?
137
158
 
138
159
  ptr = domains_ptr.read_pointer
@@ -141,7 +162,7 @@ module Libvirt
141
162
 
142
163
  def list_all_storage_pools_qty(options_or_flags = nil)
143
164
  flags = Util.parse_flags options_or_flags, FFI::Storage.enum_type(:list_all_pools_flags)
144
- result = FFI::Storage.virConnectListAllStoragePools(@conn_ptr, nil, flags)
165
+ result = FFI::Storage.virConnectListAllStoragePools(@ptr, nil, flags)
145
166
  raise Errors::LibError, "Couldn't retrieve storage pools qty with flags #{flags.to_s(16)}" if result.negative?
146
167
 
147
168
  result
@@ -153,19 +174,73 @@ module Libvirt
153
174
  return [] if size.zero?
154
175
 
155
176
  storage_pools_ptr = ::FFI::MemoryPointer.new(:pointer, size)
156
- result = FFI::Storage.virConnectListAllStoragePools(@conn_ptr, storage_pools_ptr, flags)
177
+ result = FFI::Storage.virConnectListAllStoragePools(@ptr, storage_pools_ptr, flags)
157
178
  raise Errors::LibError, "Couldn't retrieve storage pools list with flags #{flags.to_s(16)}" if result.negative?
158
179
 
159
180
  ptr = storage_pools_ptr.read_pointer
160
181
  ptr.get_array_of_pointer(0, size).map { |stp_ptr| StoragePool.new(stp_ptr) }
161
182
  end
162
183
 
184
+ # @param options_or_flags [Array<Symbol>,Hash{Symbol=>Boolean},Integer,Symbol,nil]
185
+ # @return [Integer]
186
+ # @raise [Libvirt::Errors::LibError]
187
+ def list_all_networks_qty(options_or_flags = nil)
188
+ flags = Util.parse_flags options_or_flags, FFI::Network.enum_type(:list_all_flags)
189
+ result = FFI::Network.virConnectListAllNetworks(@ptr, nil, flags)
190
+ raise Errors::LibError, "Couldn't retrieve networks qty with flags #{flags.to_s(16)}" if result.negative?
191
+
192
+ result
193
+ end
194
+
195
+ # @param options_or_flags [Array<Symbol>,Hash{Symbol=>Boolean},Integer,Symbol,nil]
196
+ # @return [Array<Libvirt::Network>, Array]
197
+ # @raise [Libvirt::Errors::LibError]
198
+ def list_all_networks(options_or_flags = nil)
199
+ flags = Util.parse_flags options_or_flags, FFI::Network.enum_type(:list_all_flags)
200
+ size = list_all_networks_qty(flags)
201
+ return [] if size.zero?
202
+
203
+ networks_ptr = ::FFI::MemoryPointer.new(:pointer, size)
204
+ result = FFI::Network.virConnectListAllNetworks(@ptr, networks_ptr, 0)
205
+ raise Errors::LibError, "Couldn't retrieve networks list" if result.negative?
206
+
207
+ ptr = networks_ptr.read_pointer
208
+ ptr.get_array_of_pointer(0, size).map { |n_ptr| Network.new(n_ptr) }
209
+ end
210
+
211
+ # @param options_or_flags [Array<Symbol>,Hash{Symbol=>Boolean},Integer,Symbol,nil]
212
+ # @return [Integer]
213
+ # @raise [Libvirt::Errors::LibError]
214
+ def list_all_interfaces_qty(options_or_flags = nil)
215
+ flags = Util.parse_flags options_or_flags, FFI::Interface.enum_type(:list_all_flags)
216
+ result = FFI::Interface.virConnectListAllInterfaces(@ptr, nil, flags)
217
+ raise Errors::LibError, "Couldn't retrieve interfaces qty with flags #{flags.to_s(16)}" if result.negative?
218
+
219
+ result
220
+ end
221
+
222
+ # @param options_or_flags [Array<Symbol>,Hash{Symbol=>Boolean},Integer,Symbol,nil]
223
+ # @return [Array<Libvirt::Interface>, Array]
224
+ # @raise [Libvirt::Errors::LibError]
225
+ def list_all_interfaces(options_or_flags = nil)
226
+ flags = Util.parse_flags options_or_flags, FFI::Interface.enum_type(:list_all_flags)
227
+ size = list_all_interfaces_qty(flags)
228
+ return [] if size.zero?
229
+
230
+ interfaces_ptr = ::FFI::MemoryPointer.new(:pointer, size)
231
+ result = FFI::Interface.virConnectListAllInterfaces(@ptr, interfaces_ptr, 0)
232
+ raise Errors::LibError, "Couldn't retrieve interfaces list" if result.negative?
233
+
234
+ ptr = interfaces_ptr.read_pointer
235
+ ptr.get_array_of_pointer(0, size).map { |i_ptr| Interface.new(i_ptr) }
236
+ end
237
+
163
238
  def register_close_callback(opaque = nil, &block)
164
- dbg { "#register_close_callback opaque=#{opaque}" }
239
+ dbg { "opaque=#{opaque}" }
165
240
 
166
241
  cb_data, cb_data_free_func = CLOSE_STORAGE.allocate_struct
167
242
  result = FFI::Host.virConnectRegisterCloseCallback(
168
- @conn_ptr,
243
+ @ptr,
169
244
  CLOSE_CALLBACK,
170
245
  cb_data.pointer,
171
246
  cb_data_free_func
@@ -177,17 +252,29 @@ module Libvirt
177
252
 
178
253
  CLOSE_STORAGE.store_struct(
179
254
  cb_data,
180
- connection_pointer: @conn_ptr,
255
+ connection_pointer: @ptr,
181
256
  callback_id: result,
182
257
  cb: block,
183
- opaque: opaque
258
+ opaque: opaque,
259
+ free_func: cb_data_free_func
184
260
  )
185
261
  result
186
262
  end
187
263
 
264
+ def deregister_close_callback
265
+ dbg { 'deregister' }
266
+
267
+ result = FFI::Host.virConnectUnregisterCloseCallback(@ptr, CLOSE_CALLBACK)
268
+ raise Errors::LibError, "Couldn't deregister close callback" if result.negative?
269
+
270
+ # virConnectUnregisterCloseCallback will call free func
271
+ # So we don't need to remove object from CLOSE_STORAGE here.
272
+ true
273
+ end
274
+
188
275
  # @yield conn, dom, *args
189
276
  def register_domain_event_callback(event_id, domain = nil, opaque = nil, &block)
190
- dbg { "#register_domain_event_callback event_id=#{event_id}" }
277
+ dbg { "event_id=#{event_id}" }
191
278
 
192
279
  enum = FFI::Domain.enum_type(:event_id)
193
280
  event_id, event_id_sym = Util.parse_enum(enum, event_id)
@@ -196,7 +283,7 @@ module Libvirt
196
283
  cb_data, cb_data_free_func = DOMAIN_STORAGE.allocate_struct
197
284
 
198
285
  result = FFI::Domain.virConnectDomainEventRegisterAny(
199
- @conn_ptr,
286
+ @ptr,
200
287
  domain&.to_ptr,
201
288
  event_id,
202
289
  cb,
@@ -213,15 +300,16 @@ module Libvirt
213
300
  connection_pointer: @conn_ptr,
214
301
  callback_id: result,
215
302
  cb: block,
216
- opaque: opaque
303
+ opaque: opaque,
304
+ free_func: cb_data_free_func
217
305
  )
218
306
  result
219
307
  end
220
308
 
221
309
  def deregister_domain_event_callback(callback_id)
222
- dbg { "#deregister_domain_event_callback callback_id=#{callback_id}" }
310
+ dbg { "callback_id=#{callback_id}" }
223
311
 
224
- result = FFI::Domain.virConnectDomainEventDeregisterAny(@conn_ptr, callback_id)
312
+ result = FFI::Domain.virConnectDomainEventDeregisterAny(@ptr, callback_id)
225
313
  raise Errors::LibError, "Couldn't deregister domain event callback" if result.negative?
226
314
 
227
315
  # virConnectDomainEventDeregisterAny will call free func
@@ -230,7 +318,7 @@ module Libvirt
230
318
  end
231
319
 
232
320
  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}" }
321
+ dbg { "event_id=#{event_id}" }
234
322
 
235
323
  enum = FFI::Storage.enum_type(:event_id)
236
324
  event_id, event_id_sym = Util.parse_enum(enum, event_id)
@@ -239,7 +327,7 @@ module Libvirt
239
327
  cb_data, cb_data_free_func = POOL_STORAGE.allocate_struct
240
328
 
241
329
  result = FFI::Storage.virConnectStoragePoolEventRegisterAny(
242
- @conn_ptr,
330
+ @ptr,
243
331
  storage_pool&.to_ptr,
244
332
  event_id,
245
333
  cb,
@@ -253,18 +341,19 @@ module Libvirt
253
341
 
254
342
  POOL_STORAGE.store_struct(
255
343
  cb_data,
256
- connection_pointer: @conn_ptr,
344
+ connection_pointer: @ptr,
257
345
  callback_id: result,
258
346
  cb: block,
259
- opaque: opaque
347
+ opaque: opaque,
348
+ free_func: cb_data_free_func
260
349
  )
261
350
  result
262
351
  end
263
352
 
264
353
  def deregister_storage_pool_event_callback(callback_id)
265
- dbg { "#deregister_storage_pool_event_callback callback_id=#{callback_id}" }
354
+ dbg { "callback_id=#{callback_id}" }
266
355
 
267
- result = FFI::Storage.virConnectStoragePoolEventDeregisterAny(@conn_ptr, callback_id)
356
+ result = FFI::Storage.virConnectStoragePoolEventDeregisterAny(@ptr, callback_id)
268
357
  raise Errors::LibError, "Couldn't deregister storage pool event callback" if result.negative?
269
358
 
270
359
  # virConnectStoragePoolEventDeregisterAny will call free func
@@ -272,20 +361,53 @@ module Libvirt
272
361
  true
273
362
  end
274
363
 
275
- def deregister_close_callback
276
- dbg { '#deregister_close_callback' }
364
+ def register_network_event_callback(event_id, network = nil, opaque = nil, &block)
365
+ dbg { "event_id=#{event_id}" }
277
366
 
278
- result = FFI::Host.virConnectUnregisterCloseCallback(@conn_ptr, CLOSE_CALLBACK)
279
- raise Errors::LibError, "Couldn't deregister close callback" if result.negative?
367
+ enum = FFI::Network.enum_type(:event_id)
368
+ event_id, event_id_sym = Util.parse_enum(enum, event_id)
369
+ cb = NETWORK_EVENT_CALLBACKS.fetch(event_id_sym)
280
370
 
281
- # virConnectUnregisterCloseCallback will call free func
282
- # So we don't need to remove object from CLOSE_STORAGE here.
371
+ cb_data, cb_data_free_func = NETWORK_STORAGE.allocate_struct
372
+
373
+ result = FFI::Network.virConnectNetworkEventRegisterAny(
374
+ @ptr,
375
+ network&.to_ptr,
376
+ event_id,
377
+ cb,
378
+ cb_data.pointer,
379
+ cb_data_free_func
380
+ )
381
+ if result.negative?
382
+ cb_data.pointer.free
383
+ raise Errors::LibError, "Couldn't register network event callback"
384
+ end
385
+
386
+ NETWORK_STORAGE.store_struct(
387
+ cb_data,
388
+ connection_pointer: @ptr,
389
+ callback_id: result,
390
+ cb: block,
391
+ opaque: opaque,
392
+ free_func: cb_data_free_func
393
+ )
394
+ result
395
+ end
396
+
397
+ def deregister_network_event_callback(callback_id)
398
+ dbg { "callback_id=#{callback_id}" }
399
+
400
+ result = FFI::Network.virConnectNetworkEventDeregisterAny(@ptr, callback_id)
401
+ raise Errors::LibError, "Couldn't deregister network event callback" if result.negative?
402
+
403
+ # virConnectNetworkEventDeregisterAny will call free func
404
+ # So we don't need to remove object from NETWORK_STORAGE here.
283
405
  true
284
406
  end
285
407
 
286
408
  def lib_version
287
409
  version_ptr = ::FFI::MemoryPointer.new(:ulong)
288
- result = FFI::Host.virConnectGetLibVersion(@conn_ptr, version_ptr)
410
+ result = FFI::Host.virConnectGetLibVersion(@ptr, version_ptr)
289
411
  raise Errors::LibError, "Couldn't get connection lib version" if result.negative?
290
412
 
291
413
  version_number = version_ptr.get_ulong(0)
@@ -293,28 +415,28 @@ module Libvirt
293
415
  end
294
416
 
295
417
  def hostname
296
- FFI::Host.virConnectGetHostname(@conn_ptr)
418
+ FFI::Host.virConnectGetHostname(@ptr)
297
419
  end
298
420
 
299
421
  # @param type [String,NilClass]
300
422
  def max_vcpus(type = nil)
301
- FFI::Host.virConnectGetMaxVcpus(@conn_ptr, type)
423
+ FFI::Host.virConnectGetMaxVcpus(@ptr, type)
302
424
  end
303
425
 
304
426
  def capabilities
305
- FFI::Host.virConnectGetCapabilities(@conn_ptr)
427
+ FFI::Host.virConnectGetCapabilities(@ptr)
306
428
  end
307
429
 
308
430
  def node_info
309
431
  node_info_ptr = ::FFI::MemoryPointer.new(FFI::Host::NodeInfoStruct.by_value)
310
- result = FFI::Host.virNodeGetInfo(@conn_ptr, node_info_ptr)
432
+ result = FFI::Host.virNodeGetInfo(@ptr, node_info_ptr)
311
433
  raise Errors::LibError, "Couldn't get connection node info" if result.negative?
312
434
 
313
435
  NodeInfo.new(node_info_ptr)
314
436
  end
315
437
 
316
438
  def stream(flags = 0)
317
- pointer = FFI::Stream.virStreamNew(@conn_ptr, flags)
439
+ pointer = FFI::Stream.virStreamNew(@ptr, flags)
318
440
  raise Errors::LibError, "Couldn't create stream" if pointer.null?
319
441
 
320
442
  Stream.new(pointer)
@@ -322,24 +444,61 @@ module Libvirt
322
444
 
323
445
  def define_domain(xml, options_or_flags = nil)
324
446
  flags = Util.parse_flags options_or_flags, FFI::Domain.enum_type(:define_flags)
325
- pointer = FFI::Domain.virDomainDefineXMLFlags(@conn_ptr, xml, flags)
447
+ pointer = FFI::Domain.virDomainDefineXMLFlags(@ptr, xml, flags)
326
448
  raise Errors::LibError, "Couldn't define domain" if pointer.null?
327
449
 
328
450
  Domain.new(pointer)
329
451
  end
330
452
 
331
- private
453
+ # @param xml [String]
454
+ # @raise [Libvirt::Errors::LibError]
455
+ def create_network(xml)
456
+ pointer = FFI::Network.virNetworkCreateXML(@ptr, xml)
457
+ raise Errors::LibError, "Couldn't create network with xml" if pointer.null?
332
458
 
333
- def set_connection(conn_ptr)
334
- @conn_ptr = conn_ptr
459
+ Network.new(pointer)
335
460
  end
336
461
 
337
- def check_open!
338
- raise Errors::LibError, "Connection to #{@uri.inspect} is not open" if @conn_ptr.null?
462
+ # @param xml [String]
463
+ # @raise [Libvirt::Errors::LibError]
464
+ def define_network(xml)
465
+ pointer = FFI::Network.virNetworkDefineXML(@ptr, xml)
466
+ raise Errors::LibError, "Couldn't define network with xml" if pointer.null?
467
+
468
+ Network.new(pointer)
339
469
  end
340
470
 
341
- def dbg(&block)
342
- Util.log(:debug, 'Libvirt::Connection', &block)
471
+ # @param xml [String]
472
+ # @raise [Libvirt::Errors::LibError]
473
+ def define_interface(xml)
474
+ pointer = FFI::Interface.virInterfaceDefineXML(@ptr, xml, 0)
475
+ raise Errors::LibError, "Couldn't define interface with xml" if pointer.null?
476
+
477
+ Interface.new(pointer)
478
+ end
479
+
480
+ # @raise [Libvirt::Errors::LibError]
481
+ def begin_interface_change
482
+ result = FFI::Interface.virInterfaceChangeBegin(@ptr, 0)
483
+ raise Errors::LibError, "Couldn't begin interface change" if result.negative?
484
+ end
485
+
486
+ # @raise [Libvirt::Errors::LibError]
487
+ def commit_interface_change
488
+ result = FFI::Interface.virInterfaceChangeCommit(@ptr, 0)
489
+ raise Errors::LibError, "Couldn't commit interface change" if result.negative?
490
+ end
491
+
492
+ # @raise [Libvirt::Errors::LibError]
493
+ def rollback_interface_change
494
+ result = FFI::Interface.virInterfaceChangeRollback(@ptr, 0)
495
+ raise Errors::LibError, "Couldn't rollback interface change" if result.negative?
496
+ end
497
+
498
+ private
499
+
500
+ def check_open!
501
+ raise Errors::LibError, "Connection to #{@uri.inspect} is not open" if @ptr.null?
343
502
  end
344
503
  end
345
504
  end