libvirt_ffi 0.5.6 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|