libvirt_ffi 0.7.0 → 0.8.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.
@@ -0,0 +1,176 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Libvirt
4
+ class Network
5
+ # @param pointer [FFI::Pointer]
6
+ def self.load_ref(pointer)
7
+ result = FFI::Network.virNetworkRef(pointer)
8
+ raise Errors::LibError, "Couldn't retrieve network reference" if result.negative?
9
+
10
+ new(pointer)
11
+ end
12
+
13
+ # @param pointer [FFI::Pointer]
14
+ def initialize(pointer)
15
+ @ptr = pointer
16
+
17
+ free = ->(obj_id) do
18
+ dbg { "Finalize Libvirt::Network object_id=0x#{obj_id.to_s(16)}, pointer=0x#{@ptr.address.to_s(16)}" }
19
+ return unless @ptr
20
+
21
+ warn "Couldn't free Libvirt::Network object_id=0x#{obj_id.to_s(16)}, pointer=0x#{@ptr.address.to_s(16)}" if FFI::Network.virNetworkFree(@ptr).negative?
22
+ end
23
+ ObjectSpace.define_finalizer(self, free)
24
+ end
25
+
26
+ # @return [FFI::Pointer]
27
+ def to_ptr
28
+ @ptr
29
+ end
30
+
31
+ # @return [String]
32
+ # @raise [Libvirt::Errors::LibError]
33
+ def uuid
34
+ buff = ::FFI::MemoryPointer.new(:char, Util::UUID_STRING_BUFLEN)
35
+ result = FFI::Network.virNetworkGetUUIDString(@ptr, buff)
36
+ raise Errors::LibError, "Couldn't get network uuid" if result.negative?
37
+
38
+ buff.read_string
39
+ end
40
+
41
+ # @return [String]
42
+ # @raise [Libvirt::Errors::LibError]
43
+ def name
44
+ result = FFI::Network.virNetworkGetName(@ptr)
45
+ raise Errors::LibError, "Couldn't get network name" if result.nil?
46
+
47
+ result
48
+ end
49
+
50
+ # @param options_or_flags [Array<Symbol>,Hash{Symbol=>Boolean},Integer,Symbol,nil]
51
+ # @raise [Libvirt::Errors::LibError]
52
+ def xml_desc(options_or_flags = nil)
53
+ flags = Util.parse_flags options_or_flags, FFI::Network.enum_type(:xml_flags)
54
+ result = FFI::Network.virNetworkGetXMLDesc(@ptr, flags)
55
+ raise Errors::LibError, "Couldn't get network xml_desc" if result.nil?
56
+
57
+ result
58
+ end
59
+
60
+ # @return [Boolean]
61
+ # @raise [Libvirt::Errors::LibError]
62
+ def active?
63
+ result = FFI::Network.virNetworkIsActive(@ptr)
64
+ raise Errors::LibError, "Couldn't get network is active" if result.nil?
65
+
66
+ result == 1
67
+ end
68
+
69
+ # @return [Boolean]
70
+ # @raise [Libvirt::Errors::LibError]
71
+ def persistent?
72
+ result = FFI::Network.virNetworkIsPersistent(@ptr)
73
+ raise Errors::LibError, "Couldn't get network is persistent" if result.nil?
74
+
75
+ result == 1
76
+ end
77
+
78
+ # @return [String]
79
+ # @raise [Libvirt::Errors::LibError]
80
+ def bridge_name
81
+ result = FFI::Network.virNetworkGetBridgeName(@ptr)
82
+ raise Errors::LibError, "Couldn't get network bridge_name" if result.nil?
83
+
84
+ result
85
+ end
86
+
87
+ # @return [Boolean]
88
+ # @raise [Libvirt::Errors::LibError]
89
+ def auto_start?
90
+ value = ::FFI::MemoryPointer.new(:int)
91
+ result = FFI::Network.virNetworkGetAutostart(@ptr, value)
92
+ raise Errors::LibError, "Couldn't get network auto_start" if result.negative?
93
+
94
+ value.read_int == 1
95
+ end
96
+
97
+ # @param value [Boolean]
98
+ # @raise [Libvirt::Errors::LibError]
99
+ def set_auto_start(value)
100
+ value = value ? 1 : 0
101
+ result = FFI::Network.virNetworkSetAutostart(@ptr, value)
102
+ raise Errors::LibError, "Couldn't set network auto_start" if result.negative?
103
+ end
104
+
105
+ # @param mac [String]
106
+ # @return [Integer]
107
+ # @raise [Libvirt::Errors::LibError]
108
+ def dhcp_leases_qty(mac = nil)
109
+ result = FFI::Network.virNetworkGetDHCPLeases(@ptr, mac, nil, 0)
110
+ raise Errors::LibError, "Couldn't get network dhcp leases qty" if result.nil?
111
+
112
+ result
113
+ end
114
+
115
+ # @param mac [String]
116
+ # @return [Array<Libvirt::NetworkDhcpLease>, Array]
117
+ # @raise [Libvirt::Errors::LibError]
118
+ def dhcp_leases(mac = nil)
119
+ size = dhcp_leases_qty(mac)
120
+ return [] if size.zero?
121
+
122
+ dhcp_leases_ptr = ::FFI::MemoryPointer.new(:pointer, size)
123
+ result = FFI::Network.virNetworkGetDHCPLeases(@ptr, mac, dhcp_leases_ptr, 0)
124
+ raise Errors::LibError, "Couldn't retrieve network dhcp leases" if result.negative?
125
+
126
+ ptr = dhcp_leases_ptr.read_pointer
127
+ ptr.get_array_of_pointer(0, size).map { |dhcpl_ptr| NetworkDhcpLease.new(dhcpl_ptr) }
128
+ end
129
+
130
+ # @raise [Libvirt::Errors::LibError]
131
+ def start
132
+ result = FFI::Network.virNetworkCreate(@ptr)
133
+ raise Errors::LibError, "Couldn't start network" if result.negative?
134
+ end
135
+
136
+ # @raise [Libvirt::Errors::LibError]
137
+ def destroy
138
+ result = FFI::Network.virNetworkDestroy(@ptr)
139
+ raise Errors::LibError, "Couldn't destroy network" if result.negative?
140
+ end
141
+
142
+ # @raise [Libvirt::Errors::LibError]
143
+ def undefine
144
+ result = FFI::Network.virNetworkUndefine(@ptr)
145
+ raise Errors::LibError, "Couldn't undefine network" if result.negative?
146
+ end
147
+
148
+ # @param xml [String]
149
+ # @param command [Integer, Symbol]
150
+ # @param section [Integer, Symbol]
151
+ # @param flags [Integer, Symbol]
152
+ # @param parent_index [Integer] default -1 (means don't care)
153
+ # @raise [Libvirt::Errors::LibError]
154
+ def update(xml, command, section, flags, parent_index = -1)
155
+ command = Util.parse_flags command, FFI::Network.enum_type(:update_command)
156
+ section = Util.parse_flags section, FFI::Network.enum_type(:update_section)
157
+ flags = Util.parse_flags flags, FFI::Network.enum_type(:update_flags)
158
+
159
+ result = FFI::Network.virNetworkUpdate(
160
+ @ptr,
161
+ command,
162
+ section,
163
+ parent_index,
164
+ xml,
165
+ flags
166
+ )
167
+ raise Errors::LibError, "Couldn't update network" if result.negative?
168
+ end
169
+
170
+ private
171
+
172
+ def dbg(&block)
173
+ Util.log(:debug, 'Libvirt::Network', &block)
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Libvirt
4
+ class NetworkDhcpLease < BaseInfo
5
+ struct_class FFI::Network::DhcpLeaseStruct
6
+
7
+ # @param pointer [FFI::Pointer]
8
+ def initialize(pointer)
9
+ super
10
+
11
+ free = ->(obj_id) do
12
+ dbg { "Finalize Libvirt::NetworkDhcpLease object_id=0x#{obj_id.to_s(16)}, pointer=0x#{@ptr.address.to_s(16)}" }
13
+ return unless @ptr
14
+
15
+ warn "Couldn't free Libvirt::NetworkDhcpLease object_id=0x#{obj_id.to_s(16)}, pointer=0x#{@ptr.address.to_s(16)}" if FFI::Storage.virNetworkDHCPLeaseFree(@ptr).negative?
16
+ end
17
+ ObjectSpace.define_finalizer(self, free)
18
+ end
19
+ end
20
+ end
@@ -13,7 +13,7 @@ module Libvirt
13
13
  @ptr = pointer
14
14
 
15
15
  free = ->(obj_id) do
16
- Util.log(:debug) { "Finalize Libvirt::StoragePool 0x#{obj_id.to_s(16)} @ptr=#{@ptr}," }
16
+ dbg { "Finalize Libvirt::StoragePool 0x#{obj_id.to_s(16)} @ptr=#{@ptr}," }
17
17
  return unless @ptr
18
18
 
19
19
  fr_result = FFI::Storage.virStoragePoolFree(@ptr)
@@ -79,7 +79,7 @@ module Libvirt
79
79
  private
80
80
 
81
81
  def dbg(&block)
82
- Util.log(:debug, 'Libvirt::Domain', &block)
82
+ Util.log(:debug, 'Libvirt::StoragePool', &block)
83
83
  end
84
84
  end
85
85
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Libvirt
4
- VERSION = '0.7.0'
4
+ VERSION = '0.8.0'
5
5
  end
@@ -13,6 +13,9 @@ module Libvirt
13
13
  require 'libvirt/xml/generic'
14
14
  require 'libvirt/xml/storage_pool'
15
15
  require 'libvirt/xml/storage_volume'
16
+ require 'libvirt/xml/interface'
17
+ require 'libvirt/xml/ip_address'
18
+ require 'libvirt/xml/network'
16
19
  require 'libvirt/xml/memory'
17
20
  require 'libvirt/xml/graphics'
18
21
  require 'libvirt/xml/disk'
@@ -3,6 +3,9 @@
3
3
  module Libvirt
4
4
  module Xml
5
5
  class Generic
6
+ TRUE_VALUES = %w[yes on].freeze
7
+ FALSE_VALUES = %w[no off].freeze
8
+
6
9
  class_attribute :_root_path, instance_writer: false, default: '.'
7
10
  class_attribute :_attributes_opts, instance_writer: false, default: {}
8
11
 
@@ -111,7 +114,7 @@ module Libvirt
111
114
  # @param opts [Hash{Symbol=>Object}]
112
115
  # @return [Object, nil]
113
116
  def decode(value, opts)
114
- return if value.nil?
117
+ return opts[:default] if value.nil?
115
118
 
116
119
  cast = opts[:cast]
117
120
  return value if cast.nil?
@@ -144,9 +147,9 @@ module Libvirt
144
147
  def decode_bool(value, _opts)
145
148
  return value if value.is_a?(TrueClass) || value.is_a?(FalseClass)
146
149
 
147
- return true if value == 'yes'
150
+ return true if TRUE_VALUES.include?(value)
148
151
 
149
- return false if value == 'no'
152
+ return false if FALSE_VALUES.include?(value)
150
153
 
151
154
  nil
152
155
  end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Libvirt
4
+ module Xml
5
+ class Interface < Generic
6
+ # no official doc found
7
+ #
8
+ # <interface type='ethernet' name='lo'>
9
+ # <protocol family='ipv4'>
10
+ # <ip address='127.0.0.1' prefix='8'/>
11
+ # </protocol>
12
+ # <protocol family='ipv6'>
13
+ # <ip address='::1' prefix='128'/>
14
+ # </protocol>
15
+ # <link state='unknown'/>
16
+ # </interface>
17
+ #
18
+ # <interface type='bridge'>
19
+ # <mac address='52:54:00:4f:7e:b2'/>
20
+ # <source bridge='vbr107'/>
21
+ # <target dev='vnet4'/>
22
+ # <model type='virtio'/>
23
+ # <alias name='net0'/>
24
+ # <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
25
+ # </interface>
26
+
27
+ root_path './interface'
28
+
29
+ attribute :type, type: :attr
30
+
31
+ attribute :name, type: :attr
32
+ attribute :link_state, type: :attr, path: './link', name: 'state'
33
+ attribute :ip_addresses, type: :ip_addresses
34
+
35
+ attribute :mac_address, type: :attr, path: './mac', name: 'address'
36
+ attribute :source_bridge, type: :attr, path: './source', name: 'bridge'
37
+ attribute :target_dev, type: :attr, path: './target', name: 'dev'
38
+ attribute :model_type, type: :attr, path: './model', name: 'type'
39
+ attribute :alias_names, type: :attr, path: './alias', name: 'name', array: true
40
+ attribute :addresses, type: :addresses
41
+
42
+ private
43
+
44
+ def parse_node_addresses(_, _opts)
45
+ nodes = find_nodes(nil, path: './address')
46
+
47
+ nodes.map do |node|
48
+ {
49
+ type: node['type'],
50
+ domain: node['domain'],
51
+ bus: node['bus'],
52
+ slot: node['slot'],
53
+ function: node['function']
54
+ }
55
+ end
56
+ end
57
+
58
+ def parse_node_ip_addresses(_, _opts)
59
+ protocols = find_nodes(nil, path: './protocol')
60
+ ip_addresses = []
61
+
62
+ protocols.each do |protocol|
63
+ family = protocol['family']
64
+
65
+ protocol.xpath('./ip').each do |ip|
66
+ # ip['netmask'], ip['localPtr']
67
+ ip_addresses.push(
68
+ address: ip['address'],
69
+ prefix: ip['prefix'],
70
+ family: family
71
+ )
72
+ end
73
+ end
74
+
75
+ ip_addresses
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Libvirt
4
+ module Xml
5
+ class IpAddress < Generic
6
+ # https://libvirt.org/formatnetwork.html#elementsAddress
7
+
8
+ # <ip address="192.168.122.1" netmask="255.255.255.0" localPtr="yes">
9
+ # <dhcp>
10
+ # <range start="192.168.122.100" end="192.168.122.254"/>
11
+ # <host mac="00:16:3e:77:e2:ed" name="foo.example.com" ip="192.168.122.10"/>
12
+ # <host mac="00:16:3e:3e:a9:1a" name="bar.example.com" ip="192.168.122.11"/>
13
+ # </dhcp>
14
+ # </ip>
15
+ # <ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64" localPtr="yes"/>
16
+ attribute :address, type: :attr
17
+ attribute :netmask, type: :attr
18
+ attribute :prefix, type: :attr
19
+ attribute :local_ptr, type: :attr, name: 'localPtr', cast: :bool, default: false
20
+ attribute :family, type: :attr, default: 'ipv4'
21
+ attribute :tftp_root, type: :attr, path: './tftp', name: 'root'
22
+ attribute :dhcp_ranges, type: :dhcp_ranges
23
+ attribute :dhcp_hosts, type: :dhcp_hosts
24
+ attribute :dhcp_bootp_file, type: :attr, path: './dhcp/bootp', name: 'file'
25
+ attribute :dhcp_bootp_server, type: :attr, path: './dhcp/bootp', name: 'server'
26
+
27
+ private
28
+
29
+ def parse_node_dhcp_ranges(_, _opts)
30
+ nodes = find_nodes(nil, path: './dhcp/range')
31
+
32
+ nodes.map do |node|
33
+ [node['start'], node['end']]
34
+ end
35
+ end
36
+
37
+ def parse_node_dhcp_hosts(_, _opts)
38
+ nodes = find_nodes(nil, path: './dhcp/host')
39
+
40
+ nodes.map do |node|
41
+ {
42
+ mac: node['mac'],
43
+ ip: node['ip'],
44
+ name: node['name'],
45
+ host: node['host']
46
+ }
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,204 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Libvirt
4
+ module Xml
5
+ class Network < Generic
6
+ # https://libvirt.org/formatnetwork.html
7
+
8
+ root_path './network'
9
+
10
+ # <network ipv6='yes' trustGuestRxFilters='no'>
11
+ # ...
12
+ attribute :ipv6, type: :attr, cast: :bool, default: false
13
+
14
+ attribute :trust_guest_rx_filters,
15
+ type: :attr,
16
+ name: 'trustGuestRxFilters',
17
+ cast: :bool,
18
+ default: false
19
+
20
+ # <name>default</name>
21
+ # <uuid>3e3fce45-4f53-4fa7-bb32-11f34168b82b</uuid>
22
+ attribute :name
23
+ attribute :uuid
24
+
25
+ # <metadata>
26
+ # <app1:foo xmlns:app1="http://app1.org/app1/">..</app1:foo>
27
+ # <app2:bar xmlns:app2="http://app1.org/app2/">..</app2:bar>
28
+ # </metadata>
29
+ attribute :metadata, type: :raw
30
+
31
+ # <bridge name="virbr0" stp="on" delay="5" macTableManager="libvirt"/>
32
+ attribute :bridge_name,
33
+ type: :attr,
34
+ name: 'name',
35
+ path: './bridge'
36
+
37
+ attribute :bridge_stp,
38
+ type: :attr,
39
+ name: 'stp',
40
+ cast: :bool,
41
+ path: './bridge'
42
+
43
+ attribute :bridge_delay,
44
+ type: :attr,
45
+ name: 'delay',
46
+ cast: :int,
47
+ path: './bridge'
48
+
49
+ attribute :bridge_mac_table_manager,
50
+ type: :attr,
51
+ name: 'macTableManager',
52
+ path: './bridge'
53
+
54
+ # <mtu size="9000"/>
55
+ attribute :mtu_size, type: :attr, path: './mtu', name: 'size', cast: :int
56
+
57
+ # <domain name="example.com" localOnly="no"/>
58
+ attribute :domain_name, type: :attr, path: './domain', name: 'name'
59
+ attribute :domain_local_only, type: :attr, path: './domain', name: 'localOnly', cast: :bool
60
+
61
+ # <forward mode='nat' dev='eth0'>
62
+ # <nat>
63
+ # <address start='1.2.3.4' end='1.2.3.10'/>
64
+ # </nat>
65
+ # </forward>
66
+ attribute :forward_mode, type: :attr, path: './forward', name: 'mode'
67
+ attribute :forward_dev, type: :attr, path: './forward', name: 'dev'
68
+ attribute :forward_nat_address, type: :forward_nat, node_name: :address
69
+ attribute :forward_nat_port, type: :forward_nat, node_name: :port
70
+
71
+ # <forward mode='passthrough'>
72
+ # <interface dev='eth10'/>
73
+ # <interface dev='eth11'/>
74
+ # <interface dev='eth12'/>
75
+ # <interface dev='eth13'/>
76
+ # <interface dev='eth14'/>
77
+ # </forward>
78
+ attribute :forward_interfaces,
79
+ type: :attr,
80
+ path: './forward/interface',
81
+ name: 'dev',
82
+ array: true
83
+
84
+ # <forward mode='passthrough'>
85
+ # <pf dev='eth0'/>
86
+ # </forward>
87
+ attribute :forward_pf,
88
+ type: :attr,
89
+ path: './forward/pf',
90
+ name: 'dev',
91
+ array: true
92
+
93
+ # <forward mode='hostdev' managed='yes'>
94
+ # <driver name='vfio'/>
95
+ # <address type='pci' domain='0' bus='4' slot='0' function='1'/>
96
+ # <address type='pci' domain='0' bus='4' slot='0' function='2'/>
97
+ # <address type='pci' domain='0' bus='4' slot='0' function='3'/>
98
+ # </forward>
99
+ attribute :forward_manager,
100
+ type: :attr,
101
+ path: './forward',
102
+ name: 'managed',
103
+ cast: :bool,
104
+ default: false
105
+
106
+ attribute :forward_driver,
107
+ type: :attr,
108
+ path: './forward/driver',
109
+ name: 'name'
110
+
111
+ attribute :forward_addresses, type: :forward_hostdev_address
112
+
113
+ attribute :mac_address,
114
+ type: :attr,
115
+ path: './mac',
116
+ name: 'address'
117
+
118
+ # <dns>
119
+ # <txt name="example" value="example value"/>
120
+ # <forwarder addr="8.8.8.8"/>
121
+ # <forwarder domain='example.com' addr="8.8.4.4"/>
122
+ # <forwarder domain='www.example.com'/>
123
+ # <srv service='name' protocol='tcp' domain='test-domain-name' target='.'
124
+ # port='1024' priority='10' weight='10'/>
125
+ # <host ip='192.168.122.2'>
126
+ # <hostname>myhost</hostname>
127
+ # <hostname>myhostalias</hostname>
128
+ # </host>
129
+ # </dns>
130
+ attribute :dns_forwarder, type: :dns_forwarder
131
+ attribute :dns_txt, type: :dns_txt
132
+ attribute :dns_host_ip, type: :attr, path: './dns/host', name: 'ip'
133
+ attribute :dns_hostnames, path: './dns/host/hostname', array: true
134
+ attribute :dns_srv, type: :dns_txt
135
+
136
+ attribute :ip_addresses, type: :struct, path: './ip', class: IpAddress, array: true
137
+
138
+ # https://libvirt.org/formatnetwork.html#elementQoS
139
+ # TODO continue from <bandwidth>
140
+
141
+ private
142
+
143
+ def parse_node_forward_nat(_, opts)
144
+ nodes = find_nodes(nil, path: "./forward/nat/#{opts[:node_name]}")
145
+
146
+ nodes.map do |node|
147
+ [node['start'], node['stop']]
148
+ end
149
+ end
150
+
151
+ def parse_node_forward_hostdev_address(_, _opts)
152
+ nodes = find_nodes(nil, path: './forward/address')
153
+
154
+ nodes.map do |node|
155
+ {
156
+ type: node['type'],
157
+ domain: node['domain'],
158
+ bus: node['bus'],
159
+ slot: node['slot'],
160
+ function: node['function']
161
+ }
162
+ end
163
+ end
164
+
165
+ def parse_node_dns_forwarder(_, _opts)
166
+ nodes = find_nodes(nil, path: './dns/forwarder')
167
+
168
+ nodes.map do |node|
169
+ {
170
+ domain: node['domain'],
171
+ addr: node['addr']
172
+ }
173
+ end
174
+ end
175
+
176
+ def parse_node_dns_txt(_, _opts)
177
+ nodes = find_nodes(nil, path: './dns/txt')
178
+
179
+ nodes.map do |node|
180
+ {
181
+ name: node['name'],
182
+ value: node['value']
183
+ }
184
+ end
185
+ end
186
+
187
+ def parse_node_dns_srv(_, _opts)
188
+ nodes = find_nodes(nil, path: './dns/srv')
189
+
190
+ nodes.map do |node|
191
+ {
192
+ name: node['name'],
193
+ protocol: node['protocol'],
194
+ target: node['target'],
195
+ port: node['port'],
196
+ priority: node['priority'],
197
+ weight: node['weight'],
198
+ domain: node['domain']
199
+ }
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end