libvirt_ffi 0.5.6 → 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.
- checksums.yaml +4 -4
- data/lib/libvirt.rb +3 -1
- data/lib/libvirt/base_info.rb +8 -0
- data/lib/libvirt/connection.rb +267 -22
- data/lib/libvirt/domain.rb +23 -2
- data/lib/libvirt/ffi.rb +2 -0
- data/lib/libvirt/ffi/domain.rb +57 -43
- data/lib/libvirt/ffi/host.rb +9 -1
- data/lib/libvirt/ffi/interface.rb +175 -0
- data/lib/libvirt/ffi/network.rb +392 -0
- data/lib/libvirt/ffi/storage.rb +85 -0
- data/lib/libvirt/{domain_callback_storage.rb → host_callback_storage.rb} +19 -8
- data/lib/libvirt/interface.rb +92 -0
- data/lib/libvirt/network.rb +176 -0
- data/lib/libvirt/network_dhcp_lease.rb +20 -0
- data/lib/libvirt/storage_pool.rb +17 -2
- data/lib/libvirt/util.rb +2 -0
- data/lib/libvirt/version.rb +1 -1
- data/lib/libvirt/xml.rb +3 -0
- data/lib/libvirt/xml/generic.rb +6 -3
- data/lib/libvirt/xml/interface.rb +79 -0
- data/lib/libvirt/xml/ip_address.rb +51 -0
- data/lib/libvirt/xml/network.rb +204 -0
- data/test_usage/test_interface.rb +47 -0
- data/test_usage/test_network.rb +73 -0
- metadata +13 -3
@@ -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
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'libvirt'
|
6
|
+
require 'logger'
|
7
|
+
require 'active_support/all'
|
8
|
+
require 'async'
|
9
|
+
require 'json'
|
10
|
+
|
11
|
+
require_relative 'support/libvirt_async'
|
12
|
+
require_relative 'support/log_formatter'
|
13
|
+
|
14
|
+
require 'libvirt/xml'
|
15
|
+
|
16
|
+
Libvirt.logger = Logger.new(STDOUT, formatter: LogFormatter.new)
|
17
|
+
Libvirt.logger.level = ENV['DEBUG'] ? :debug : :info
|
18
|
+
|
19
|
+
IMPL = LibvirtAsync::Implementations.new
|
20
|
+
|
21
|
+
Async do
|
22
|
+
ASYNC_REACTOR = Async::Task.current.reactor
|
23
|
+
|
24
|
+
puts "Lib version #{Libvirt.lib_version}"
|
25
|
+
puts "Gem version #{Libvirt::VERSION}"
|
26
|
+
|
27
|
+
IMPL.start
|
28
|
+
|
29
|
+
conn = Libvirt::Connection.new('qemu+tcp://localhost:16510/system')
|
30
|
+
conn.open
|
31
|
+
|
32
|
+
puts "Connection version #{conn.version.inspect}"
|
33
|
+
puts "Connection lib_version #{conn.lib_version.inspect}"
|
34
|
+
puts "Connection hostname #{conn.hostname.inspect}"
|
35
|
+
|
36
|
+
interfaces = conn.list_all_interfaces
|
37
|
+
puts "Connection interfaces qty #{interfaces.size}"
|
38
|
+
|
39
|
+
interfaces.each.with_index do |interface, i|
|
40
|
+
puts "Interface #{i} name=#{interface.name}"
|
41
|
+
puts "Interface #{i} active?=#{interface.active?}"
|
42
|
+
puts "Interface #{i} mac=#{interface.mac}"
|
43
|
+
puts "Interface #{i} xml_desc", interface.xml_desc
|
44
|
+
puts "Interface #{i} xml", JSON.pretty_generate(Libvirt::Xml::Interface.load(interface.xml_desc).to_h)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'libvirt'
|
6
|
+
require 'logger'
|
7
|
+
require 'active_support/all'
|
8
|
+
require 'async'
|
9
|
+
require 'json'
|
10
|
+
|
11
|
+
require_relative 'support/libvirt_async'
|
12
|
+
require_relative 'support/log_formatter'
|
13
|
+
|
14
|
+
require 'libvirt/xml'
|
15
|
+
|
16
|
+
Libvirt.logger = Logger.new(STDOUT, formatter: LogFormatter.new)
|
17
|
+
Libvirt.logger.level = ENV['DEBUG'] ? :debug : :info
|
18
|
+
|
19
|
+
IMPL = LibvirtAsync::Implementations.new
|
20
|
+
|
21
|
+
Async do
|
22
|
+
ASYNC_REACTOR = Async::Task.current.reactor
|
23
|
+
|
24
|
+
puts "Lib version #{Libvirt.lib_version}"
|
25
|
+
puts "Gem version #{Libvirt::VERSION}"
|
26
|
+
|
27
|
+
IMPL.start
|
28
|
+
|
29
|
+
conn = Libvirt::Connection.new('qemu+tcp://localhost:16510/system')
|
30
|
+
conn.open
|
31
|
+
|
32
|
+
puts "Connection version #{conn.version.inspect}"
|
33
|
+
puts "Connection lib_version #{conn.lib_version.inspect}"
|
34
|
+
puts "Connection hostname #{conn.hostname.inspect}"
|
35
|
+
|
36
|
+
networks = conn.list_all_networks
|
37
|
+
puts "Connection networks qty #{networks.size}"
|
38
|
+
|
39
|
+
networks.each.with_index do |network, i|
|
40
|
+
puts "Network #{i} uuid=#{network.uuid}"
|
41
|
+
puts "Network #{i} name=#{network.name}"
|
42
|
+
puts "Network #{i} active?=#{network.active?}"
|
43
|
+
puts "Network #{i} persistent?=#{network.persistent?}"
|
44
|
+
puts "Network #{i} auto_start=#{network.auto_start?}"
|
45
|
+
puts "Network #{i} bridge_name=#{network.bridge_name}"
|
46
|
+
puts "Network #{i} xml_desc", network.xml_desc
|
47
|
+
puts "Network #{i} xml", JSON.pretty_generate(Libvirt::Xml::Network.load(network.xml_desc).to_h)
|
48
|
+
end
|
49
|
+
|
50
|
+
networks.each.with_index do |network, i|
|
51
|
+
dhcp_leases = network.dhcp_leases
|
52
|
+
puts "Network #{i} DHCP Leases size=#{dhcp_leases.size}"
|
53
|
+
|
54
|
+
dhcp_leases.each.with_index do |dhcp, j|
|
55
|
+
puts "Network #{i} DHCP Lease #{j} name=#{dhcp.name}"
|
56
|
+
puts "Network #{i} DHCP Lease #{j} iface=#{dhcp.iface}"
|
57
|
+
puts "Network #{i} DHCP Lease #{j} expirytime=#{dhcp.expirytime}"
|
58
|
+
puts "Network #{i} DHCP Lease #{j} type=#{dhcp.type}"
|
59
|
+
puts "Network #{i} DHCP Lease #{j} mac=#{dhcp.mac}"
|
60
|
+
puts "Network #{i} DHCP Lease #{j} iaid=#{dhcp.iaid}"
|
61
|
+
puts "Network #{i} DHCP Lease #{j} ipaddr=#{dhcp.ipaddr}"
|
62
|
+
puts "Network #{i} DHCP Lease #{j} prefix=#{dhcp.prefix}"
|
63
|
+
puts "Network #{i} DHCP Lease #{j} hostname=#{dhcp.hostname}"
|
64
|
+
puts "Network #{i} DHCP Lease #{j} clientid=#{dhcp.clientid}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
puts 'register_network_event_callback'
|
69
|
+
conn.register_network_event_callback(:LIFECYCLE) do |_c, net, event, detail, opaque|
|
70
|
+
puts "NETWORK LIFECYCLE EVENT name=#{net.name}, event=#{event}, detail=#{detail}, opaque=#{opaque}"
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|